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
//! Module providing a special pointer trait used to transfer owned data and to
//! allow safer transmuation of data without forgetting to change other pointer
//! types.
//!
//! Pointer types need to implement the trait in this module, if they want to
//! support this library.
//!
//! The type system is used to enforce as much as possible, but implementors
//! still need to pay attention, that their type can implemen [`OwnedUniquePtr<T>`].
use crate::transmute::TransmuteInto;
use core::{ops::DerefMut, pin::Pin};
// used to dissallow other crates implementing TypesEq.
mod sealed {
pub struct Sealed;
}
#[doc(hidden)]
pub trait TypesEq<T: ?Sized> {
fn __no_impls_outside_this_crate(_: sealed::Sealed);
}
impl<T: ?Sized> TypesEq<T> for T {
fn __no_impls_outside_this_crate(_: sealed::Sealed) {}
}
/// A (smart) unique pointer which owns its data (e.g. [`alloc::boxed::Box`]).
/// This pointer provides access to T via [`DerefMut`].
///
/// Transmuting the pointee is also supported, if it implements
/// [`TransmuteInto<U>`] for some `U`.
///
/// # Safety
///
/// All types implementing this trait need to
/// - own the data they point to.
/// - be the only way to access the data behind this pointer.
/// - provide the same pointer type as `Self` with only a different pointee via the
/// [`Self::Ptr`] associated type.
pub unsafe trait OwnedUniquePtr<T: ?Sized>: DerefMut<Target = T> + Sized
where
Self: TypesEq<Self::Ptr<T>>,
{
/// Access the same underlying pointer type with a different pointee type.
/// `Self == Self::Ptr<T>`
type Ptr<U: ?Sized>: DerefMut<Target = U>;
/// Transmute the type behind this pointer while being pinned.
///
/// # Safety
///
/// This function does not
/// - move the pointee.
/// - mutate the pointee.
/// The caller needs to guarantee, that it is safe to transmute `T` to `U` (or
/// equivalently, that it is safe to call [`TransmuteInto::transmute_ptr`]).
unsafe fn transmute_pointee_pinned<U>(this: Pin<Self>) -> Pin<Self::Ptr<U>>
where
T: TransmuteInto<U>;
}
#[cfg(feature = "alloc")]
unsafe impl<T: ?Sized> OwnedUniquePtr<T> for alloc::boxed::Box<T> {
type Ptr<U: ?Sized> = alloc::boxed::Box<U>;
#[inline]
unsafe fn transmute_pointee_pinned<U>(this: Pin<Self>) -> Pin<Self::Ptr<U>>
where
T: TransmuteInto<U>,
{
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
unsafe {
// SAFETY: we later repin the pointer and never move the data behind it.
let this = Pin::into_inner_unchecked(this);
// this is safe, due to the requriements of this function
let this: Box<U> = Box::from_raw(Box::into_raw(this) as *mut U);
Pin::new_unchecked(this)
}
}
}