#![no_std]
extern crate alloc;
use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::sync::Arc;
use core::cmp;
use core::fmt::{self, Debug, Display, Pointer};
use core::hash::{Hash, Hasher};
use core::ops::{Deref, DerefMut};
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct SuperPin<Ptr> {
pointer: Ptr,
}
#[macro_export]
macro_rules! superpin {
($value: expr $(,)?) => {
$crate::SuperPin<&mut _> { pointer: &mut { $value } }
};
}
impl<Ptr: Debug> Debug for SuperPin<Ptr> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.pointer, f)
}
}
impl<Ptr: Display> Display for SuperPin<Ptr> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.pointer, f)
}
}
impl<Ptr: Pointer> Pointer for SuperPin<Ptr> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&self.pointer, f)
}
}
impl<Ptr: Deref, Q: Deref> PartialEq<SuperPin<Q>> for SuperPin<Ptr>
where
Ptr::Target: PartialEq<Q::Target>,
{
fn eq(&self, other: &SuperPin<Q>) -> bool {
Ptr::Target::eq(self, other)
}
#[allow(clippy::partialeq_ne_impl)] // We need to copy what the Ptr type does
fn ne(&self, other: &SuperPin<Q>) -> bool {
Ptr::Target::ne(self, other)
}
}
impl<Ptr: Deref<Target: Eq>> Eq for SuperPin<Ptr> {}
impl<Ptr: Deref, Q: Deref> PartialOrd<SuperPin<Q>> for SuperPin<Ptr>
where
Ptr::Target: PartialOrd<Q::Target>,
{
fn partial_cmp(&self, other: &SuperPin<Q>) -> Option<cmp::Ordering> {
Ptr::Target::partial_cmp(self, other)
}
fn lt(&self, other: &SuperPin<Q>) -> bool {
Ptr::Target::lt(self, other)
}
fn le(&self, other: &SuperPin<Q>) -> bool {
Ptr::Target::le(self, other)
}
fn gt(&self, other: &SuperPin<Q>) -> bool {
Ptr::Target::gt(self, other)
}
fn ge(&self, other: &SuperPin<Q>) -> bool {
Ptr::Target::ge(self, other)
}
}
impl<Ptr: Deref<Target: Ord>> Ord for SuperPin<Ptr> {
fn cmp(&self, other: &Self) -> cmp::Ordering {
Ptr::Target::cmp(self, other)
}
}
impl<Ptr: Deref> Hash for SuperPin<Ptr>
where
<Ptr as Deref>::Target: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
self.pointer.hash(state);
}
}
impl<Ptr: Deref> Deref for SuperPin<Ptr> {
type Target = Ptr::Target;
fn deref(&self) -> &Self::Target {
&self.pointer
}
}
impl<Ptr: DerefMut> DerefMut for SuperPin<Ptr> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.pointer
}
}
impl<T: ?Sized> From<Box<T>> for SuperPin<Box<T>> {
fn from(value: Box<T>) -> Self {
// safety: It's not possible to move or replace the insides of a
// SuperPin<Box<T>>, so it's safe to pin it directly without
// any additional requirements.
unsafe { Self::new_unchecked(value) }
}
}
impl<Ptr> SuperPin<Ptr> {
pub fn boxed<T>(x: T) -> SuperPin<Box<T>> {
SuperPin::from(Box::new(x))
}
pub fn rc<T>(value: T) -> SuperPin<Rc<T>> {
// safety: It's not possible to move anything behind an Rc
unsafe { SuperPin::new_unchecked(Rc::new(value)) }
}
pub fn arc<T>(value: T) -> SuperPin<Arc<T>> {
// safety: It's not possible to move anything behind an Arc
unsafe { SuperPin::new_unchecked(Arc::new(value)) }
}
}
impl<Ptr: Deref> SuperPin<Ptr> {
pub unsafe fn new_unchecked(pointer: Ptr) -> Self {
Self { pointer }
}
pub fn as_ref(&self) -> SuperPin<&<Ptr as Deref>::Target> {
// safety: the pointee cannot move while it is pinned
unsafe { SuperPin::new_unchecked(self.pointer.deref()) }
}
pub unsafe fn into_inner_unchecked(pin: SuperPin<Ptr>) -> Ptr {
// safety: the caller must ensure that the value is not moved
pin.pointer
}
}
impl<Ptr: DerefMut> SuperPin<Ptr> {
pub fn as_mut(&mut self) -> SuperPin<&mut <Ptr as Deref>::Target> {
// safety: the pointee cannot move while it is pinned
unsafe { SuperPin::new_unchecked(self.pointer.deref_mut()) }
}
pub fn set(&mut self, value: <Ptr as Deref>::Target)
where
<Ptr as Deref>::Target: Sized,
{
// safety: the destructor is run and a new valid value of the same type is
// put in its place, so no pinning invariant is violated
*self.pointer.deref_mut() = value;
}
}
impl<'a, T: ?Sized> SuperPin<&'a T> {
pub unsafe fn map_unchecked<U: ?Sized>(self, func: impl FnOnce(&T) -> &U) -> SuperPin<&'a U> {
let new_pointer = func(self.pointer);
// safety: the caller is responsible for upholding the invariants of
// SuperPin::new_unchecked
unsafe { SuperPin::new_unchecked(new_pointer) }
}
pub fn get_ref(self) -> &'a T {
// safety: it is impossible to move out of a shared pointer
self.pointer
}
}
impl<'a, T: ?Sized> SuperPin<&'a mut T> {
pub fn into_ref(self) -> SuperPin<&'a T> {
// safety: it is impossible to move out of a shared pointer
unsafe { SuperPin::new_unchecked(&*self.pointer) }
}
pub unsafe fn get_unchecked_mut(self) -> &'a mut T {
// safety: the caller must ensure the value is not moved out of the pointer
self.pointer
}
pub unsafe fn map_unchecked_mut<U: ?Sized>(
self,
func: impl FnOnce(&mut T) -> &mut U,
) -> SuperPin<&'a mut U> {
let pointer = &mut *self.pointer;
let new_pointer = func(pointer);
// safety: the caller must uphold the invariants of SuperPin::new_unchecked
unsafe { SuperPin::new_unchecked(new_pointer) }
}
}
impl<T: ?Sized> SuperPin<&'static T> {
pub fn static_ref(r: &'static T) -> Self {
// safety: T is borrowed for the 'static lifetime, which never ends
unsafe { SuperPin::new_unchecked(r) }
}
}
impl<T: ?Sized> SuperPin<&'static mut T> {
pub fn static_mut(r: &'static mut T) -> Self {
// safety: T is borrowed for the 'static lifetime, which never ends
unsafe { SuperPin::new_unchecked(r) }
}
}
impl<'a, T> SuperPin<&'a Option<T>> {
pub fn as_option_ref(self) -> Option<SuperPin<&'a T>> {
unsafe {
SuperPin::get_ref(self)
.as_ref()
// safety: x has to be pinned, because it comes from self
.map(|x| SuperPin::new_unchecked(x))
}
}
}
impl<'a, T> SuperPin<&'a mut Option<T>> {
pub fn as_option_mut(self) -> Option<SuperPin<&'a mut T>> {
unsafe {
// safety: the value is never moved
SuperPin::get_unchecked_mut(self)
.as_mut()
// safety: x has to be pinned, because it comes from self
.map(|x| SuperPin::new_unchecked(x))
}
}
}
|