use crate::{DowncastUnchecked, DynDynBase, DynDynCastTarget, DynDynTable, GetDynDynTable};
use core::cmp::Ordering;
use core::fmt::{self, Display, Pointer};
use core::hash::{Hash, Hasher};
use core::marker::{PhantomData, Unsize};
use core::ops::CoerceUnsized;
use core::ops::{Deref, DerefMut};
use core::ptr::{self, DynMetadata};
use stable_deref_trait::{CloneStableDeref, StableDeref};
#[derive(Debug)]
pub struct DynDynFat<B: ?Sized + DynDynBase, P> {
ptr: P,
table: DynDynTable,
_base: PhantomData<fn(B) -> B>,
}
impl<B: ?Sized + DynDynBase, P: GetDynDynTable<B>> DynDynFat<B, P> {
pub unsafe fn new_unchecked(ptr: P, table: DynDynTable) -> Self {
DynDynFat {
ptr,
table,
_base: PhantomData,
}
}
pub fn new(ptr: P) -> Self {
let table = ptr.get_dyn_dyn_table();
unsafe { Self::new_unchecked(ptr, table) }
}
pub fn get_dyn_dyn_table(ptr: &Self) -> DynDynTable {
ptr.table
}
pub fn unwrap(ptr: Self) -> P {
ptr.ptr
}
}
impl<B: ?Sized + DynDynBase, P: Deref> DynDynFat<B, P>
where
P::Target: Unsize<B>,
{
pub fn deref_fat(ptr: &Self) -> DynDynFat<B, &P::Target> {
DynDynFat {
ptr: ptr.ptr.deref(),
table: ptr.table,
_base: PhantomData,
}
}
}
impl<B: ?Sized + DynDynBase, P: DerefMut> DynDynFat<B, P>
where
P::Target: Unsize<B>,
{
pub fn deref_mut_fat(ptr: &mut Self) -> DynDynFat<B, &mut P::Target> {
DynDynFat {
ptr: ptr.ptr.deref_mut(),
table: ptr.table,
_base: PhantomData,
}
}
}
impl<B: ?Sized + DynDynBase, P: Clone> DynDynFat<B, P> {
pub unsafe fn clone_unchecked(ptr: &Self) -> Self {
DynDynFat {
ptr: ptr.ptr.clone(),
table: ptr.table,
_base: PhantomData,
}
}
}
unsafe impl<B: ?Sized + DynDynBase, P: GetDynDynTable<B>> GetDynDynTable<B> for DynDynFat<B, P> {
type DynTarget = P::DynTarget;
fn get_dyn_dyn_table(&self) -> DynDynTable {
self.table
}
}
impl<'a, B: ?Sized + DynDynBase, P: DowncastUnchecked<'a, B> + 'a> DowncastUnchecked<'a, B>
for DynDynFat<B, P>
{
type DowncastResult<D: ?Sized + 'a> = <P as DowncastUnchecked<'a, B>>::DowncastResult<D>;
unsafe fn downcast_unchecked<D: ?Sized + DynDynCastTarget>(
self,
metadata: DynMetadata<D::Root>,
) -> Self::DowncastResult<D> {
unsafe { self.ptr.downcast_unchecked(metadata) }
}
}
impl<B: ?Sized + DynDynBase, P: Deref> Deref for DynDynFat<B, P> {
type Target = P::Target;
fn deref(&self) -> &Self::Target {
self.ptr.deref()
}
}
unsafe impl<B: ?Sized + DynDynBase, P: StableDeref> StableDeref for DynDynFat<B, P> {}
unsafe impl<B: ?Sized + DynDynBase, P: CloneStableDeref + GetDynDynTable<B>> CloneStableDeref
for DynDynFat<B, P>
{
}
impl<B: ?Sized + DynDynBase, P: DerefMut> DerefMut for DynDynFat<B, P> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.ptr.deref_mut()
}
}
impl<B: ?Sized + DynDynBase, P: Deref + Clone + GetDynDynTable<B>> Clone for DynDynFat<B, P> {
fn clone(&self) -> Self {
let ptr = self.ptr.clone();
let table = if ptr::eq(ptr.deref(), self.ptr.deref()) {
self.table
} else {
<P as GetDynDynTable<B>>::get_dyn_dyn_table(&ptr)
};
DynDynFat {
ptr,
table,
_base: PhantomData,
}
}
}
impl<B: ?Sized + DynDynBase, P: Deref + Copy + GetDynDynTable<B>> Copy for DynDynFat<B, P> where
P::Target: Unsize<B>
{
}
impl<B: ?Sized + DynDynBase, P: GetDynDynTable<B> + Default> Default for DynDynFat<B, P> {
fn default() -> Self {
DynDynFat::new(Default::default())
}
}
impl<B: ?Sized + DynDynBase, P: GetDynDynTable<B>> From<P> for DynDynFat<B, P> {
fn from(ptr: P) -> Self {
DynDynFat::new(ptr)
}
}
impl<B: ?Sized + DynDynBase, P: Deref> AsRef<P> for DynDynFat<B, P> {
fn as_ref(&self) -> &P {
&self.ptr
}
}
impl<B1: ?Sized + DynDynBase, B2: ?Sized + DynDynBase, P1: Deref, P2: Deref>
PartialEq<DynDynFat<B2, P2>> for DynDynFat<B1, P1>
where
P1::Target: Unsize<B1> + PartialEq<P2::Target>,
P2::Target: Unsize<B2>,
{
fn eq(&self, other: &DynDynFat<B2, P2>) -> bool {
PartialEq::eq(&*self.ptr, &*other.ptr)
}
}
impl<B: ?Sized + DynDynBase, P: Deref> Eq for DynDynFat<B, P> where P::Target: Unsize<B> + Eq {}
impl<B: ?Sized + DynDynBase, P: Deref> Hash for DynDynFat<B, P>
where
P::Target: Unsize<B> + Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
Hash::hash(&*self.ptr, state)
}
}
impl<B1: ?Sized + DynDynBase, B2: ?Sized + DynDynBase, P1: Deref, P2: Deref>
PartialOrd<DynDynFat<B2, P2>> for DynDynFat<B1, P1>
where
P1::Target: Unsize<B1> + PartialOrd<P2::Target>,
P2::Target: Unsize<B2>,
{
fn partial_cmp(&self, other: &DynDynFat<B2, P2>) -> Option<Ordering> {
PartialOrd::partial_cmp(&*self.ptr, &*other.ptr)
}
}
impl<B: ?Sized + DynDynBase, P: Deref> Ord for DynDynFat<B, P>
where
P::Target: Unsize<B> + Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&*self.ptr, &*other.ptr)
}
}
impl<B: ?Sized + DynDynBase, P1: Deref + CoerceUnsized<P2>, P2: Deref>
CoerceUnsized<DynDynFat<B, P2>> for DynDynFat<B, P1>
where
P1::Target: Unsize<B>,
P2::Target: Unsize<B>,
{
}
impl<B: ?Sized + DynDynBase, P: Display> Display for DynDynFat<B, P> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.ptr)
}
}
impl<B: ?Sized + DynDynBase, P: Pointer> Pointer for DynDynFat<B, P> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:p}", self.ptr)
}
}