pub unsafe trait Ointer<const N: usize> {
type Pointer;
const LOW_MASK: usize = { !0usize >> N };
const HIGH_MASK: usize = { !Self::LOW_MASK };
const MIN_SIGNED: isize = { isize::MIN >> Self::SHIFT_BITS };
const MAX_SIGNED: isize = { isize::MAX >> Self::SHIFT_BITS };
const SHIFT_BITS: usize = {
if cfg!(target_pointer_width = "128") {
128 - N
} else if cfg!(target_pointer_width = "64") {
64 - N
} else if cfg!(target_pointer_width = "32") {
32 - N
} else if cfg!(target_pointer_width = "16") {
16 - N
} else {
panic!("Unsupported target pointer width")
}
};
#[inline(always)]
fn get_bool(&self) -> bool {
self.get_usize() != 0
}
#[inline(always)]
fn get_isize(&self) -> isize {
unsafe { *(self as *const Self as *const isize) >> Self::SHIFT_BITS }
}
#[inline(always)]
fn get_usize(&self) -> usize {
unsafe { *(self as *const Self as *const usize) >> Self::SHIFT_BITS }
}
#[inline(always)]
fn get_ptr_as_usize(&self) -> usize {
unsafe { *(self as *const Self as *const usize) & Self::LOW_MASK }
}
#[inline(always)]
fn set_bool(&mut self, b: bool) {
self.set_isize(if b { -1 } else { 0 })
}
#[inline(always)]
fn set_isize(&mut self, i: isize) {
if i < Self::MIN_SIGNED || i > Self::MAX_SIGNED {
panic!("No enough bits to be stolen.")
}
let p = self as *mut Self as *mut usize;
unsafe {
*p = (*p & Self::LOW_MASK) | ((i as usize) << Self::SHIFT_BITS);
}
}
#[inline(always)]
fn set_usize(&mut self, u: usize) {
if (u >> N) != 0 {
panic!("No enough bits to be stolen.")
}
let p = self as *mut Self as *mut usize;
unsafe {
*p = (*p & Self::LOW_MASK) | (u << Self::SHIFT_BITS);
}
}
#[inline(always)]
fn set_ptr(&mut self, p: &mut Self::Pointer) {
let u = unsafe { *(p as *mut Self::Pointer as *mut usize) };
unsafe {
*(self as *mut Self as *mut usize) = u;
}
self.assert_stealable();
}
#[inline(always)]
fn assert_stealable(&self) {
assert_eq!(self.get_bool(), false);
}
#[inline(always)]
fn get<T: Copy>(&self) -> T
where
Self: OinterGet<T, N>,
{
self.get_high_bits()
}
#[inline(always)]
fn set_mut<T: Copy>(&mut self, x: T)
where
Self: OinterSet<T, N>,
{
self.set_high_bits_mut(x);
}
#[inline(always)]
fn map<T: Copy, R, F: FnOnce(T, &Self::Pointer) -> R>(&self, f: F) -> R
where
Self: OinterGet<T, N>,
{
let x = self.get_high_bits();
let u = self.get_ptr_as_usize();
let p = unsafe { &*(&u as *const usize as *const Self::Pointer) };
f(x, p)
}
#[inline(always)]
fn map_mut<T: Copy, R, F: FnOnce(&mut T, &mut Self::Pointer) -> R>(&mut self, f: F) -> R
where
Self: OinterGet<T, N> + OinterSet<T, N>,
{
let mut x = self.get_high_bits();
let mut u = self.get_ptr_as_usize();
let p = unsafe { &mut *(&mut u as *mut usize as *mut Self::Pointer) };
let ret = f(&mut x, p);
self.set_ptr(p);
self.set_high_bits_mut(x);
ret
}
}
pub unsafe trait OinterGet<T: Copy, const N: usize>: Ointer<N> {
#[inline(always)]
fn get_high_bits(&self) -> T {
use core::mem::size_of;
let u = self.get_usize();
let x = if size_of::<T>() == 8 {
unsafe { *(&(u as u64) as *const u64 as *const T) }
} else if size_of::<T>() == 4 {
unsafe { *(&(u as u32) as *const u32 as *const T) }
} else if size_of::<T>() == 2 {
unsafe { *(&(u as u16) as *const u16 as *const T) }
} else if size_of::<T>() == 1 {
unsafe { *(&(u as u8) as *const u8 as *const T) }
} else {
panic!("Unsupported value size")
};
x
}
}
pub unsafe trait OinterSet<T: Copy, const N: usize>: Ointer<N> {
#[inline(always)]
fn set_high_bits_mut(&mut self, x: T) {
use core::mem::size_of;
let u: usize = if size_of::<T>() == 8 {
unsafe { *(&x as *const T as *const u64) }
.try_into()
.unwrap()
} else if size_of::<T>() == 4 {
unsafe { *(&x as *const T as *const u32) }
.try_into()
.unwrap()
} else if size_of::<T>() == 2 {
unsafe { *(&x as *const T as *const u16) }
.try_into()
.unwrap()
} else if size_of::<T>() == 1 {
unsafe { *(&x as *const T as *const u8) }
.try_into()
.unwrap()
} else {
panic!("Unsupported value size")
};
self.set_usize(u);
}
}
unsafe impl<const N: usize, T: Copy, Ty: Ointer<N>> OinterGet<T, N> for Ty {}
unsafe impl<const N: usize, T: Copy, Ty: Ointer<N>> OinterSet<T, N> for Ty {}
#[macro_export]
macro_rules! define_ointer {
($ointer:ident, $pointer:ident, $bits:literal) => {
#[repr(transparent)]
pub struct $ointer<T: ?Sized>($pointer<T>);
unsafe impl<T: ?Sized> Ointer<$bits> for $ointer<T> {
type Pointer = $pointer<T>;
}
impl<T: ?Sized> core::convert::From<$pointer<T>> for $ointer<T> {
fn from(p: $pointer<T>) -> Self {
let s = Self(p);
s.assert_stealable();
s
}
}
impl<T> core::default::Default for $ointer<T>
where
Self: Ointer<$bits, Pointer = $pointer<T>>,
<Self as Ointer<$bits>>::Pointer: core::default::Default,
{
fn default() -> Self {
$pointer::default().into()
}
}
impl<T: ?Sized> core::clone::Clone for $ointer<T>
where
Self: Ointer<$bits, Pointer = $pointer<T>>,
<Self as Ointer<$bits>>::Pointer: Clone,
{
fn clone(&self) -> Self {
self.map(|u: usize, p| {
let mut o = Self(p.clone());
o.set_usize(u);
o
})
}
}
impl<T: ?Sized> core::fmt::Debug for $ointer<T>
where
Self: Ointer<$bits, Pointer = $pointer<T>>,
<Self as Ointer<$bits>>::Pointer: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
self.map(|u: usize, p| (u, p).fmt(f))
}
}
impl<T: ?Sized> core::ops::Drop for $ointer<T>
where
Self: Ointer<$bits>,
{
fn drop(&mut self) {
self.set_bool(false);
}
}
impl<T: ?Sized> core::hash::Hash for $ointer<T>
where
Self: Ointer<$bits, Pointer = $pointer<T>>,
<Self as Ointer<$bits>>::Pointer: core::hash::Hash,
{
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.map(|u: usize, p| (u, p).hash(state))
}
}
impl<T: ?Sized> core::cmp::PartialEq for $ointer<T>
where
Self: Ointer<$bits, Pointer = $pointer<T>>,
<Self as Ointer<$bits>>::Pointer: core::cmp::PartialEq,
{
fn eq(&self, rhs: &Self) -> bool {
self.map(|u: usize, p| rhs.map(|c, q| (u, p).eq(&(c, q))))
}
}
impl<T: ?Sized> core::cmp::PartialOrd for $ointer<T>
where
Self: Ointer<$bits, Pointer = $pointer<T>>,
<Self as Ointer<$bits>>::Pointer: core::cmp::PartialOrd,
{
fn partial_cmp(&self, rhs: &Self) -> Option<core::cmp::Ordering> {
self.map(|u: usize, p| rhs.map(|c, q| (u, p).partial_cmp(&(c, q))))
}
}
impl<T: ?Sized> core::ops::Deref for $ointer<T>
where
Self: Ointer<$bits, Pointer = $pointer<T>>,
<Self as Ointer<$bits>>::Pointer: core::ops::Deref<Target = T>,
{
type Target = T;
fn deref(&self) -> &T {
self.map(|_: usize, p| unsafe { &*(p.deref() as *const T) })
}
}
impl<T: ?Sized> core::ops::DerefMut for $ointer<T>
where
Self: Ointer<$bits, Pointer = $pointer<T>>,
<Self as Ointer<$bits>>::Pointer: core::ops::DerefMut<Target = T>,
{
fn deref_mut(&mut self) -> &mut T {
self.map_mut(|_: &mut usize, p| unsafe { &mut *(p.deref_mut() as *mut T) })
}
}
impl<T: ?Sized> $ointer<T>
where
Self: Ointer<1>,
{
pub fn o(&self) -> bool {
self.get_bool()
}
pub fn flip(&mut self) {
self.set_bool(!self.o());
}
pub fn clone_and_flip(&self) -> Self
where
Self: Clone,
{
let mut o = self.clone();
o.flip();
o
}
}
};
}
macro_rules! define_ointer_methods {
($ointer:ident, $pointer:ident, $bits:literal) => {
impl<T> $ointer<T>
where
Self: Ointer<$bits, Pointer = $pointer<T>>,
{
pub fn new(x: T) -> Self {
$pointer::new(x).into()
}
pub fn pin(x: T) -> core::pin::Pin<Self> {
unsafe { core::pin::Pin::new_unchecked(Self::new(x)) }
}
}
};
}
pub(crate) use define_ointer_methods;
#[macro_export]
macro_rules! define_ointer_strong {
($ointer:ident, $pointer:ident, $bits:literal) => {
define_ointer!($ointer, $pointer, $bits);
define_ointer_methods!($ointer, $pointer, $bits);
};
}
#[macro_export]
macro_rules! define_shared_ointer {
($ointer_strong:ident, $pointer_strong:ident, $ointer_weak:ident, $pointer_weak:ident, $bits:literal) => {
define_ointer_strong!($ointer_strong, $pointer_strong, $bits);
define_ointer!($ointer_weak, $pointer_weak, $bits);
impl<T: ?Sized> $ointer_strong<T> {
pub fn downgrade(&self) -> $ointer_weak<T> {
self.map(|u: usize, p| {
let mut o: $ointer_weak<T> = $pointer_strong::downgrade(p).into();
o.set_usize(u);
o
})
}
pub fn strong_count(&self) -> usize {
self.map(|_: usize, p| $pointer_strong::strong_count(p))
}
pub fn weak_count(&self) -> usize {
self.map(|_: usize, p| $pointer_strong::weak_count(p))
}
}
impl<T: ?Sized> $ointer_weak<T> {
pub fn upgrade(&self) -> Option<$ointer_strong<T>> {
self.map(|u: usize, w| {
let p = w.upgrade();
p.map(|p| {
let mut o: $ointer_strong<T> = p.into();
o.set_usize(u);
o
})
})
}
}
};
}
#[macro_export]
macro_rules! define_enum_ointers {
(
$name:ident {
$($pointer:ty = $unsigned:literal),*
},
$bits:literal
) => {
paste::paste!{
#[repr(transparent)]
pub struct $name(core::num::NonZeroUsize);
unsafe impl Ointer<$bits> for $name {
type Pointer = core::num::NonZeroUsize;
}
impl $name {
#[inline(always)]
pub fn new<P: 'static>(u: usize, p: P) -> Self {
use core::any::TypeId;
use core::mem::size_of;
match u {
$($unsigned => {
if TypeId::of::<P>() != TypeId::of::<$pointer>() {
panic!("Unmatched pointer type")
}
if size_of::<P>() > size_of::<usize>() {
panic!("Size overflow")
}
let mut inner = $name(unsafe {
*(&p as *const P as *const core::num::NonZeroUsize)
});
inner.set_usize(u);
core::mem::forget(p);
inner
}),
*,
_ => panic!("Unmatched unsigned num")
}
}
#[inline(always)]
pub fn set_mut<P: 'static>(&mut self, u: usize, p: P) {
*self = Self::new(u, p);
}
#[inline(always)]
pub unsafe fn as_ointer<P: Ointer<$bits> + 'static>(&self) -> &P {
&*(self as *const Self as *const P)
}
#[inline(always)]
pub unsafe fn as_ointer_mut<P: Ointer<$bits> + 'static>(&mut self) -> &mut P {
&mut *(self as *mut Self as *mut P)
}
#[inline(always)]
pub fn map_enum<
R,
$([<F $unsigned>]: FnOnce(&$pointer) -> R),
*
>(
&self,
$([<f $unsigned>]: [<F $unsigned>]),
*
) -> R {
let u = self.get_usize();
match u {
$($unsigned => {
let mut u = self.get_ptr_as_usize();
let p = unsafe {
&mut *(&mut u as *mut usize as *mut Self)
};
p.set_usize(0);
[<f $unsigned>](unsafe {
&*(p as *const Self as *const $pointer)
})
}),
*,
_ => panic!("Unmatched unsigned num")
}
}
#[inline(always)]
pub fn map_enum_mut<
R,
$([<F $unsigned>]: FnOnce(&mut $pointer) -> R),
*
>(
&mut self,
$([<f $unsigned>]: [<F $unsigned>]),
*
) -> R {
let u = self.get_usize();
match u {
$($unsigned => {
self.set_usize(0);
let r = [<f $unsigned>](unsafe {
&mut *(self as *mut Self as *mut $pointer)
});
self.set_usize(u);
r
}),
*,
_ => panic!("Unmatched unsigned num")
}
}
}
impl core::clone::Clone for $name
where
$(
$pointer: core::clone::Clone
), *
{
fn clone(&self) -> Self {
self.map_enum($(|p| Self::new($unsigned, p.clone())), *)
}
}
impl core::ops::Drop for $name {
fn drop(&mut self) {
self.map_enum_mut(
$(|p| {
$unsigned;
unsafe {
core::mem::ManuallyDrop::drop(
&mut *(
p as *mut $pointer
as *mut core::mem::ManuallyDrop<$pointer>
)
);
}
}), *
);
}
}
}
};
}
pub use define_enum_ointers;
pub use define_ointer;
pub use define_ointer_strong;
pub use define_shared_ointer;