#![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 { pointer: Ptr, } #[macro_export] macro_rules! superpin { ($value: expr $(,)?) => { $crate::SuperPin<&mut _> { pointer: &mut { $value } } }; } impl Debug for SuperPin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.pointer, f) } } impl Display for SuperPin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.pointer, f) } } impl Pointer for SuperPin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Pointer::fmt(&self.pointer, f) } } impl PartialEq> for SuperPin where Ptr::Target: PartialEq, { fn eq(&self, other: &SuperPin) -> 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) -> bool { Ptr::Target::ne(self, other) } } impl> Eq for SuperPin {} impl PartialOrd> for SuperPin where Ptr::Target: PartialOrd, { fn partial_cmp(&self, other: &SuperPin) -> Option { Ptr::Target::partial_cmp(self, other) } fn lt(&self, other: &SuperPin) -> bool { Ptr::Target::lt(self, other) } fn le(&self, other: &SuperPin) -> bool { Ptr::Target::le(self, other) } fn gt(&self, other: &SuperPin) -> bool { Ptr::Target::gt(self, other) } fn ge(&self, other: &SuperPin) -> bool { Ptr::Target::ge(self, other) } } impl> Ord for SuperPin { fn cmp(&self, other: &Self) -> cmp::Ordering { Ptr::Target::cmp(self, other) } } impl Hash for SuperPin where ::Target: Hash, { fn hash(&self, state: &mut H) { self.pointer.hash(state); } } impl Deref for SuperPin { type Target = Ptr::Target; fn deref(&self) -> &Self::Target { &self.pointer } } impl DerefMut for SuperPin { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.pointer } } impl From> for SuperPin> { fn from(value: Box) -> Self { // safety: It's not possible to move or replace the insides of a // SuperPin>, so it's safe to pin it directly without // any additional requirements. unsafe { Self::new_unchecked(value) } } } impl SuperPin { pub fn boxed(x: T) -> SuperPin> { SuperPin::from(Box::new(x)) } pub fn rc(value: T) -> SuperPin> { // safety: It's not possible to move anything behind an Rc unsafe { SuperPin::new_unchecked(Rc::new(value)) } } pub fn arc(value: T) -> SuperPin> { // safety: It's not possible to move anything behind an Arc unsafe { SuperPin::new_unchecked(Arc::new(value)) } } } impl SuperPin { pub unsafe fn new_unchecked(pointer: Ptr) -> Self { Self { pointer } } pub fn as_ref(&self) -> SuperPin<&::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 { // safety: the caller must ensure that the value is not moved pin.pointer } } impl SuperPin { pub fn as_mut(&mut self) -> SuperPin<&mut ::Target> { // safety: the pointee cannot move while it is pinned unsafe { SuperPin::new_unchecked(self.pointer.deref_mut()) } } pub fn set(&mut self, value: ::Target) where ::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(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( 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 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 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> { pub fn as_option_ref(self) -> Option> { 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> { pub fn as_option_mut(self) -> Option> { 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)) } } }