1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use crate::traits::{StableVTableTrait, StablePointer, StablePointerLifetime, VTable, StablePointerCast};
use crate::refs::{StableRef, StableMut};
use core::ptr::NonNull;

/// A type-erased pointer with stable layout to a trait object
/// This pointer has the same layout as `*mut dyn Trait` for `#[stable_vtable]` traits
///  as with [[RFC 2955]](https://github.com/rust-lang/rfcs/pull/2955)
#[repr(C)]
pub struct StablePtr<Trait: StableVTableTrait + ?Sized>{
    pub data: *mut (),
    pub vtable: *const Trait::VTable
}

impl<Trait: StableVTableTrait + ?Sized> StablePtr<Trait>{
    pub fn is_null(self) ->bool{
        self.data.is_null()
    }
}

impl<Trait: StableVTableTrait + ?Sized> From<*mut Trait> for StablePtr<Trait>
    where Trait: StablePointerCast<StablePtr<Trait>>{
    fn from(ptr: *mut Trait) -> Self {
        unsafe { <Trait as StablePointerCast<StablePtr<Trait>>>::to_stable(ptr) }
    }
}

impl<Trait: StableVTableTrait + ?Sized> From<*const Trait> for StablePtr<Trait>
    where Trait: StablePointerCast<StablePtr<Trait>>{
    fn from(ptr: *const Trait) -> Self {
        unsafe { <Trait as StablePointerCast<StablePtr<Trait>>>::to_stable(ptr as *mut Trait) }
    }
}

/// A type-erased pointer with stable layout to a trait object
/// This pointer has the same layout as `NonNull<dyn Trait>` for `#[stable_vtable]` traits
///  as with [[RFC 2955]](https://github.com/rust-lang/rfcs/pull/2955).
/// Note: While `NonNull<T>` has special handling when inside `Option<T>`, no such guarantee is stably made.
///  There are test suites that check to ensure this is correct.
#[repr(C)]
pub struct StableNonNull<Trait: StableVTableTrait + ?Sized>{
    pub data: NonNull<()>,
    pub vtable: NonNull<Trait::VTable>
}

impl<Trait: StableVTableTrait + ?Sized> Copy for StablePtr<Trait>{}
impl<Trait: StableVTableTrait + ?Sized> Copy for StableNonNull<Trait>{}

impl<Trait: StableVTableTrait + ?Sized> Clone for StablePtr<Trait>{
    fn clone(&self) -> Self {
        *self
    }
}

impl<Trait: StableVTableTrait + ?Sized> Clone for StableNonNull<Trait>{
    fn clone(&self) -> Self {
        *self
    }
}

impl<Trait: StableVTableTrait + ?Sized> From<NonNull<Trait>> for StableNonNull<Trait>
    where Trait: StablePointerCast<StableNonNull<Trait>>{
    fn from(ptr: NonNull<Trait>) -> Self {
        unsafe { <Trait as StablePointerCast<StableNonNull<Trait>>>::to_stable(ptr.as_ptr() as *mut Trait) }
    }
}

impl<Trait: StableVTableTrait + ?Sized> From<StableNonNull<Trait>> for StablePtr<Trait>{
    fn from(ptr: StableNonNull<Trait>) -> Self {
        unsafe{ptr.into_other()}
    }
}


unsafe impl<'a,Trait: StableVTableTrait + ?Sized> StablePointerLifetime<'a,Trait> for StablePtr<Trait>{
    type Reference = StableRef<'a,Trait>;
    type MutReference = StableMut<'a,Trait>;
}

unsafe impl<Trait: StableVTableTrait + ?Sized> StablePointer<Trait> for StablePtr<Trait>{
    unsafe fn size_of_val(self) -> usize {
        (&*self.vtable.cast::<VTable>()).size
    }

    unsafe fn align_of_val(self) -> usize {
        (&*self.vtable.cast::<VTable>()).align
    }

    unsafe fn drop_in_place(self) -> () {
        if let Some(f) = (&*self.vtable.cast::<VTable>()).drop_in_place{
            (f)(self.data)
        }
    }

    unsafe fn dealloc(self) -> () {
        if let Some(f) = (&*self.vtable.cast::<VTable>()).dealloc{
            (f)(self.data)
        }
    }

    unsafe fn deref<'a>(self) -> <Self as StablePointerLifetime<'a,Trait>>::Reference
        where Trait: 'a{
        core::mem::transmute(self)
    }

    unsafe fn deref_mut<'a>(self) -> <Self as StablePointerLifetime<'a,Trait>>::MutReference
        where Trait: 'a {
        core::mem::transmute(self)
    }
}

unsafe impl<'a,Trait: StableVTableTrait + ?Sized> StablePointerLifetime<'a,Trait> for StableNonNull<Trait>{
    type Reference = StableRef<'a,Trait>;
    type MutReference = StableMut<'a,Trait>;
}

unsafe impl<Trait: StableVTableTrait + ?Sized> StablePointer<Trait> for StableNonNull<Trait>{
    unsafe fn size_of_val(self) -> usize {
        (self.vtable.cast::<VTable>().as_ref()).size
    }

    unsafe fn align_of_val(self) -> usize {
        (self.vtable.cast::<VTable>().as_ref()).align
    }

    unsafe fn drop_in_place(self) -> () {
        if let Some(f) = (self.vtable.cast::<VTable>().as_ref()).drop_in_place{
            (f)(self.data.as_ptr())
        }
    }

    unsafe fn dealloc(self) -> () {
        if let Some(f) = (self.vtable.cast::<VTable>().as_ref()).dealloc{
            (f)(self.data.as_ptr())
        }
    }

    unsafe fn deref<'a>(self) -> <Self as StablePointerLifetime<'a,Trait>>::Reference
        where Trait: 'a{
        core::mem::transmute(self)
    }

    unsafe fn deref_mut<'a>(self) -> <Self as StablePointerLifetime<'a,Trait>>::MutReference
        where Trait: 'a {
        core::mem::transmute(self)
    }
}