use std::{
ops::DerefMut,
mem::ManuallyDrop,
ptr,
};
use serde::{de, ser, Deserialize, Deserializer};
#[allow(unused_imports)]
use core_extensions::{prelude::*, ResultLike};
use crate::{
pointer_trait::{ErasedStableDeref, StableDeref, TransmuteElement},
ErasedObject,
std_types::{RBox, RCow, RStr},
};
use super::*;
use super::{
c_functions::adapt_std_fmt,
trait_objects::*,
vtable::{GetVtable, VTable},
traits::InterfaceFor,
};
#[cfg(test)]
mod tests;
mod priv_ {
use super::*;
#[repr(C)]
#[derive(StableAbi)]
#[sabi(inside_abi_stable_crate)]
pub struct VirtualWrapper<P> {
pub(super) object: ManuallyDrop<P>,
vtable: *const VTable<P>,
}
impl VirtualWrapper<()> {
pub fn from_value<T>(object: T) -> VirtualWrapper<RBox<ZeroSized<T::Interface>>>
where
T: ImplType,
T: GetVtable<T,RBox<ZeroSized<<T as ImplType>::Interface>>,RBox<T>>,
{
let object = RBox::new(object);
VirtualWrapper::from_ptr(object)
}
pub fn from_ptr<P, T>(object: P) -> VirtualWrapper<P::TransmutedPtr>
where
P: StableDeref<Target = T>,
T: ImplType,
T: GetVtable<T,P::TransmutedPtr,P>,
P: ErasedStableDeref<<T as ImplType>::Interface>,
{
VirtualWrapper {
object: ManuallyDrop::new(object.erased(T::Interface::T)),
vtable: T::get_vtable(),
}
}
pub fn from_any_value<T,I>(object: T,interface:I) -> VirtualWrapper<RBox<ZeroSized<I>>>
where
T:'static,
I:InterfaceType,
InterfaceFor<T,I> : GetVtable<T,RBox<ZeroSized<I>>,RBox<T>>,
{
let object = RBox::new(object);
VirtualWrapper::from_any_ptr(object,interface)
}
pub fn from_any_ptr<P, T,I>(object: P,_interface:I) -> VirtualWrapper<P::TransmutedPtr>
where
I:InterfaceType,
P: StableDeref<Target = T>,
T:'static,
InterfaceFor<T,I>: GetVtable<T,P::TransmutedPtr,P>,
P: ErasedStableDeref<I>,
{
VirtualWrapper {
object: ManuallyDrop::new(object.erased(I::T)),
vtable: <InterfaceFor<T,I>>::get_vtable(),
}
}
}
impl<P> VirtualWrapper<P> {
pub(super) fn vtable<'a>(&self) -> &'a VTable<P>{
unsafe {
&*self.vtable
}
}
pub fn is_same_type<Other>(&self,other:&VirtualWrapper<Other>)->bool{
self.vtable_address()==other.vtable_address()||
self.vtable().type_info().is_compatible(other.vtable().type_info())
}
pub(super)fn vtable_address(&self) -> usize {
self.vtable as usize
}
pub(super) fn as_abi(&self) -> &ErasedObject
where
P: Deref,
{
self.object()
}
#[allow(dead_code)]
pub(super) fn as_abi_mut(&mut self) -> &mut ErasedObject
where
P: DerefMut,
{
self.object_mut()
}
pub fn object_address(&self) -> usize
where
P: Deref,
{
self.object() as *const ErasedObject as usize
}
pub(super) fn object(&self) -> &ErasedObject
where
P: Deref,
{
unsafe { self.object_as() }
}
pub(super) fn object_mut(&mut self) -> &mut ErasedObject
where
P: DerefMut,
{
unsafe { self.object_as_mut() }
}
unsafe fn object_as<T>(&self) -> &T
where
P: Deref,
{
&*((&**self.object) as *const P::Target as *const T)
}
unsafe fn object_as_mut<T>(&mut self) -> &mut T
where
P: DerefMut,
{
&mut *((&mut **self.object) as *mut P::Target as *mut T)
}
}
impl<P> VirtualWrapper<P> {
pub(super) fn check_same_destructor_opaque<A,T>(&self) -> Result<(), UneraseError>
where
P: TransmuteElement<T>,
A: GetVtable<T,P,P::TransmutedPtr>,
{
let t_vtable:&VTable<P> = A::get_vtable();
if self.vtable_address() == t_vtable as *const _ as usize
|| self.vtable().type_info().is_compatible(t_vtable.type_info())
{
Ok(())
} else {
Err(UneraseError {
expected_vtable_address: t_vtable as *const _ as usize,
expected_type_info:t_vtable.type_info(),
found_vtable_address: self.vtable as usize,
found_type_info:self.vtable().type_info(),
})
}
}
pub fn into_unerased<T>(self) -> Result<P::TransmutedPtr, UneraseError>
where
P: TransmuteElement<T>,
P::Target:Sized,
T: ImplType + GetVtable<T,P,P::TransmutedPtr>,
{
self.check_same_destructor_opaque::<T,T>()?;
unsafe {
let this=ManuallyDrop::new(self);
Ok(ptr::read(&*this.object).transmute_element(T::T))
}
}
pub fn as_unerased<T>(&self) -> Result<&T, UneraseError>
where
P: Deref + TransmuteElement<T>,
T: ImplType + GetVtable<T,P,P::TransmutedPtr>,
{
self.check_same_destructor_opaque::<T,T>()?;
unsafe { Ok(self.object_as()) }
}
pub fn as_unerased_mut<T>(&mut self) -> Result<&mut T, UneraseError>
where
P: DerefMut + TransmuteElement<T>,
T: ImplType + GetVtable<T,P,P::TransmutedPtr>,
{
self.check_same_destructor_opaque::<T,T>()?;
unsafe { Ok(self.object_as_mut()) }
}
pub fn into_any_unerased<T>(self) -> Result<P::TransmutedPtr, UneraseError>
where
P: TransmuteElement<T>,
P::Target:Sized,
Self:VirtualWrapperTrait,
InterfaceFor<T,GetVWInterface<Self>>: GetVtable<T,P,P::TransmutedPtr>,
{
self.check_same_destructor_opaque::<InterfaceFor<T,GetVWInterface<Self>>,T>()?;
unsafe {
unsafe {
let this=ManuallyDrop::new(self);
Ok(ptr::read(&*this.object).transmute_element(T::T))
}
}
}
pub fn as_any_unerased<T>(&self) -> Result<&T, UneraseError>
where
P: Deref + TransmuteElement<T>,
Self:VirtualWrapperTrait,
InterfaceFor<T,GetVWInterface<Self>>: GetVtable<T,P,P::TransmutedPtr>,
{
self.check_same_destructor_opaque::<InterfaceFor<T,GetVWInterface<Self>>,T>()?;
unsafe { Ok(self.object_as()) }
}
pub fn as_any_unerased_mut<T>(&mut self) -> Result<&mut T, UneraseError>
where
P: DerefMut + TransmuteElement<T>,
Self:VirtualWrapperTrait,
InterfaceFor<T,GetVWInterface<Self>>: GetVtable<T,P,P::TransmutedPtr>,
{
self.check_same_destructor_opaque::<InterfaceFor<T,GetVWInterface<Self>>,T>()?;
unsafe { Ok(self.object_as_mut()) }
}
}
impl<P> VirtualWrapper<P> {
pub(super) fn from_new_ptr(&self, object: P) -> Self {
Self {
object:ManuallyDrop::new(object),
vtable: self.vtable,
}
}
pub fn default<I>(&self) -> Self
where
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType<Default = True>,
{
let new = self.vtable().default_ptr::<I>()();
self.from_new_ptr(new)
}
pub fn serialized<'a, I>(&'a self) -> Result<RCow<'a, RStr<'a>>, RBoxError>
where
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType<Serialize = True>,
{
self.vtable().serialize::<I>()(self.as_abi()).into_result()
}
pub fn deserialize_from_str<'a, I>(s: &'a str) -> Result<Self, RBoxError>
where
P: Deref<Target = ZeroSized<I>>,
I: DeserializeInterfaceType<Deserialize = True, Deserialized = Self>,
{
s.piped(RStr::from).piped(I::deserialize_impl)
}
}
impl<P> Drop for VirtualWrapper<P>{
fn drop(&mut self){
let vtable=self.vtable();
unsafe{
vtable.drop_ptr()(&mut *self.object);
}
}
}
}
pub use self::priv_::VirtualWrapper;
impl<P, I> Clone for VirtualWrapper<P>
where
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType<Clone = True>,
{
fn clone(&self) -> Self {
let vtable = self.vtable();
let new = vtable.clone_ptr::<I>()(&*self.object);
self.from_new_ptr(new)
}
}
impl<P, I> Display for VirtualWrapper<P>
where
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType<Display = True>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
adapt_std_fmt::<ErasedObject>(self.object(), self.vtable().display::<I>(), f)
}
}
impl<P, I> Debug for VirtualWrapper<P>
where
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType<Debug = True>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
adapt_std_fmt::<ErasedObject>(self.object(), self.vtable().debug::<I>(), f)
}
}
impl<P, I> Serialize for VirtualWrapper<P>
where
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType<Serialize = True>,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.vtable().serialize::<I>()(self.as_abi())
.into_result()
.map_err(ser::Error::custom)?
.serialize(serializer)
}
}
impl<'a, P, I> Deserialize<'a> for VirtualWrapper<P>
where
P: Deref<Target = ZeroSized<I>>,
I: DeserializeInterfaceType<Deserialize = True, Deserialized = Self>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
let s = String::deserialize(deserializer)?;
I::deserialize_impl(RStr::from(&*s)).map_err(de::Error::custom)
}
}
impl<P, I> Eq for VirtualWrapper<P>
where
Self: PartialEq,
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType<Eq = True>,
{
}
impl<P, I> PartialEq for VirtualWrapper<P>
where
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType<PartialEq = True>,
{
fn eq(&self, other: &Self) -> bool {
if !self.is_same_type(other) {
return false;
}
self.vtable().partial_eq::<I>()(self.as_abi(), other.as_abi())
}
}
impl<P, I> Ord for VirtualWrapper<P>
where
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType<Ord = True>,
Self: PartialOrd + Eq,
{
fn cmp(&self, other: &Self) -> Ordering {
if !self.is_same_type(other) {
return self.vtable_address().cmp(&other.vtable_address());
}
self.vtable().cmp::<I>()(self.as_abi(), other.as_abi()).into()
}
}
impl<P, I> PartialOrd for VirtualWrapper<P>
where
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType<PartialOrd = True>,
Self: PartialEq,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if !self.is_same_type(other) {
return Some(self.vtable_address().cmp(&other.vtable_address()));
}
self.vtable().partial_cmp::<I>()(self.as_abi(), other.as_abi())
.map(IntoReprRust::into_rust)
.into()
}
}
impl<P, I> Hash for VirtualWrapper<P>
where
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType<Hash = True>,
{
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.vtable().hash::<I>()(self.as_abi(), HasherTraitObject::new(state))
}
}
mod sealed {
use super::*;
pub trait Sealed {}
impl<P> Sealed for VirtualWrapper<P> {}
}
use self::sealed::Sealed;
pub trait VirtualWrapperTrait: Sealed {
type Interface: InterfaceType;
}
impl<P, I> VirtualWrapperTrait for VirtualWrapper<P>
where
P: Deref<Target = ZeroSized<I>>,
I: InterfaceType,
{
type Interface = I;
}
pub type GetVWInterface<This>=
<This as VirtualWrapperTrait>::Interface;
#[derive(Debug,Copy, Clone)]
pub struct UneraseError {
expected_vtable_address: usize,
expected_type_info:&'static TypeInfo,
found_vtable_address: usize,
found_type_info:&'static TypeInfo,
}
impl fmt::Display for UneraseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
impl ::std::error::Error for UneraseError {}