//! Pointers Pretending To Be Integers For Crimes -- [uptr][] and [iptr][]. #![allow(unstable_name_collisions)] use crate::Strict; /// A pointer that pretends to be an integer, for API Crimes. /// /// **Please don't use this type.** /// /// If you can't possibly satisfy strict provenance for whatever reason, you can at least /// use this type to make sure the compiler still understands that Pointers Are Happening. /// /// All operations on this type will derive provenance from the left-hand-size (lhs). /// So `x + y` has `x`'s provenance. *Many* operations are nonsensical if the pointer /// inside is a real pointer, but hey, you've reached for the "I Know What I'm Doing" /// lever, so we'll let you *say* whatever gibberish you want. /// /// Please submit a PR if you need some operation defined on usize to be exposed here. #[repr(transparent)] #[allow(non_camel_case_types)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct uptr(*mut ()); /// A pointer that pretends to be an integer, for API Crimes. /// /// **Please don't use this type.** /// /// If you can't possibly satisfy strict provenance for whatever reason, you can at least /// use this type to make sure the compiler still understands that Pointers Are Happening. /// /// All operations on this type will derive provenance from the left-hand-size (lhs). /// So `x + y` has `x`'s provenance. *Many* operations are nonsensical if the pointer /// inside is a real pointer, but hey, you've reached for the "I Know What I'm Doing" /// lever, so we'll let you *say* whatever gibberish you want. /// /// Please submit a PR if you need some operation defined on isize to be exposed here. #[repr(transparent)] #[allow(non_camel_case_types)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct iptr(*mut ()); macro_rules! int_impls { ($self_ty: ident, $int_ty: ident) => { impl $self_ty { // Inherent MIN/MAX requires 1.43 // pub const MIN: $self_ty = Self::from_int(<$int_ty>::MIN); // pub const MAX: $self_ty = Self::from_int(<$int_ty>::MAX); pub const MIN: $self_ty = Self::from_int(core::$int_ty::MIN); pub const MAX: $self_ty = Self::from_int(core::$int_ty::MAX); // Inherent BITS requires 1.53 // pub const BITS: u32 = <$int_ty>::BITS; pub const BITS: u32 = core::mem::size_of::<$int_ty>() as u32 * 8; #[inline] #[must_use] pub const fn from_int(val: $int_ty) -> Self { $self_ty(crate::invalid_mut(val as usize)) } #[inline] #[must_use] pub const fn from_ptr_mut(val: *mut T) -> Self { $self_ty(val as *mut ()) } #[inline] #[must_use] pub const fn from_ptr(val: *const T) -> Self { $self_ty(val as *const () as *mut ()) } pub const fn to_ptr(self) -> *mut () { self.0 } #[inline] #[must_use] pub fn wrapping_add(self, rhs: Self) -> Self { $self_ty( self.0.map_addr(|a| { ((a as $int_ty).wrapping_add(rhs.0.addr() as $int_ty)) as usize }), ) } #[inline] #[must_use] pub fn wrapping_sub(self, rhs: Self) -> Self { $self_ty( self.0.map_addr(|a| { ((a as $int_ty).wrapping_sub(rhs.0.addr() as $int_ty)) as usize }), ) } #[inline] #[must_use] pub fn wrapping_mul(self, rhs: Self) -> Self { $self_ty( self.0.map_addr(|a| { ((a as $int_ty).wrapping_mul(rhs.0.addr() as $int_ty)) as usize }), ) } #[inline] #[must_use] pub fn wrapping_div(self, rhs: Self) -> Self { $self_ty( self.0.map_addr(|a| { ((a as $int_ty).wrapping_div(rhs.0.addr() as $int_ty)) as usize }), ) } } impl From<$int_ty> for $self_ty { #[inline] #[must_use] fn from(val: $int_ty) -> Self { $self_ty(crate::invalid_mut(val as usize)) } } impl From<*mut T> for $self_ty { #[inline] #[must_use] fn from(val: *mut T) -> Self { $self_ty(val as *mut ()) } } impl From<*const T> for $self_ty { #[inline] #[must_use] fn from(val: *const T) -> Self { $self_ty(val as *const () as *mut ()) } } impl core::ops::Add for $self_ty { type Output = Self; #[inline] #[must_use] fn add(self, rhs: Self) -> Self::Output { $self_ty( self.0 .map_addr(|a| ((a as $int_ty) + (rhs.0.addr() as $int_ty)) as usize), ) } } impl core::ops::Sub for $self_ty { type Output = Self; #[inline] #[must_use] fn sub(self, rhs: Self) -> Self::Output { $self_ty( self.0 .map_addr(|a| ((a as $int_ty) - (rhs.0.addr() as $int_ty)) as usize), ) } } impl core::ops::Mul for $self_ty { type Output = Self; #[inline] #[must_use] fn mul(self, rhs: Self) -> Self::Output { $self_ty( self.0 .map_addr(|a| ((a as $int_ty) * (rhs.0.addr() as $int_ty)) as usize), ) } } impl core::ops::Div for $self_ty { type Output = Self; #[inline] #[must_use] fn div(self, rhs: Self) -> Self::Output { $self_ty( self.0 .map_addr(|a| ((a as $int_ty) / (rhs.0.addr() as $int_ty)) as usize), ) } } impl core::ops::Rem for $self_ty { type Output = Self; #[inline] #[must_use] fn rem(self, rhs: Self) -> Self::Output { $self_ty( self.0 .map_addr(|a| ((a as $int_ty) % (rhs.0.addr() as $int_ty)) as usize), ) } } impl core::ops::BitAnd for $self_ty { type Output = Self; #[inline] #[must_use] fn bitand(self, rhs: Self) -> Self::Output { $self_ty( self.0 .map_addr(|a| ((a as $int_ty) & (rhs.0.addr() as $int_ty)) as usize), ) } } impl core::ops::BitOr for $self_ty { type Output = Self; #[inline] #[must_use] fn bitor(self, rhs: Self) -> Self::Output { $self_ty( self.0 .map_addr(|a| ((a as $int_ty) | (rhs.0.addr() as $int_ty)) as usize), ) } } impl core::ops::BitXor for $self_ty { type Output = Self; #[inline] #[must_use] fn bitxor(self, rhs: Self) -> Self::Output { $self_ty( self.0 .map_addr(|a| ((a as $int_ty) ^ (rhs.0.addr() as $int_ty)) as usize), ) } } impl core::ops::Shl for $self_ty { type Output = Self; #[inline] #[must_use] fn shl(self, rhs: usize) -> Self::Output { $self_ty(self.0.map_addr(|a| ((a as $int_ty) << rhs) as usize)) } } impl core::ops::Shr for $self_ty { type Output = Self; #[inline] #[must_use] fn shr(self, rhs: usize) -> Self::Output { $self_ty(self.0.map_addr(|a| ((a as $int_ty) >> rhs) as usize)) } } impl core::ops::Not for $self_ty { type Output = Self; #[inline] #[must_use] fn not(self) -> Self::Output { $self_ty(self.0.map_addr(|a| (!(a as $int_ty)) as usize)) } } impl core::ops::AddAssign for $self_ty { #[inline] #[must_use] fn add_assign(&mut self, rhs: Self) { self.0 = self .0 .map_addr(|a| ((a as $int_ty) + (rhs.0.addr() as $int_ty)) as usize); } } impl core::ops::SubAssign for $self_ty { #[inline] #[must_use] fn sub_assign(&mut self, rhs: Self) { self.0 = self .0 .map_addr(|a| ((a as $int_ty) - (rhs.0.addr() as $int_ty)) as usize); } } impl core::ops::MulAssign for $self_ty { #[inline] #[must_use] fn mul_assign(&mut self, rhs: Self) { self.0 = self .0 .map_addr(|a| ((a as $int_ty) * (rhs.0.addr() as $int_ty)) as usize); } } impl core::ops::DivAssign for $self_ty { #[inline] #[must_use] fn div_assign(&mut self, rhs: Self) { self.0 = self .0 .map_addr(|a| ((a as $int_ty) / (rhs.0.addr() as $int_ty)) as usize); } } impl core::ops::RemAssign for $self_ty { #[inline] #[must_use] fn rem_assign(&mut self, rhs: Self) { self.0 = self .0 .map_addr(|a| ((a as $int_ty) % (rhs.0.addr() as $int_ty)) as usize); } } impl core::ops::BitAndAssign for $self_ty { #[inline] #[must_use] fn bitand_assign(&mut self, rhs: Self) { self.0 = self .0 .map_addr(|a| ((a as $int_ty) & (rhs.0.addr() as $int_ty)) as usize); } } impl core::ops::BitOrAssign for $self_ty { #[inline] #[must_use] fn bitor_assign(&mut self, rhs: Self) { self.0 = self .0 .map_addr(|a| ((a as $int_ty) | (rhs.0.addr() as $int_ty)) as usize); } } impl core::ops::BitXorAssign for $self_ty { #[inline] #[must_use] fn bitxor_assign(&mut self, rhs: Self) { self.0 = self .0 .map_addr(|a| ((a as $int_ty) ^ (rhs.0.addr() as $int_ty)) as usize); } } impl core::ops::ShlAssign for $self_ty { #[inline] #[must_use] fn shl_assign(&mut self, rhs: usize) { self.0 = self.0.map_addr(|a| ((a as $int_ty) << rhs) as usize); } } impl core::ops::ShrAssign for $self_ty { #[inline] #[must_use] fn shr_assign(&mut self, rhs: usize) { self.0 = self.0.map_addr(|a| ((a as $int_ty) >> rhs) as usize); } } impl core::fmt::Display for $self_ty { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{}", self.0.addr() as $int_ty) } } impl core::fmt::Debug for $self_ty { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{:?}", self.0.addr() as $int_ty) } } }; } int_impls!(uptr, usize); int_impls!(iptr, isize); // usize can't be negated impl core::ops::Neg for iptr { type Output = Self; #[inline] #[must_use] fn neg(self) -> Self::Output { iptr(self.0.map_addr(|a| (-(a as isize)) as usize)) } }