use sptr::Strict;
pub unsafe trait Backend<T> {
type Stored: Copy;
fn get_ptr(s: Self::Stored) -> (*mut T, Self);
fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored;
fn get_int(s: Self::Stored) -> Self;
}
#[cfg(test)] mod backend_size_asserts {
use core::mem;
use super::Backend;
#[allow(dead_code)] const fn assert_same_size<A, B>() {
let has_equal_size = mem::size_of::<A>() == mem::size_of::<B>();
assert!(has_equal_size);
}
#[cfg(not(target_pointer_width = "16"))]
const _: () = assert_same_size::<u128, <u128 as Backend<()>>::Stored>();
const _: () = assert_same_size::<u64, <u64 as Backend<()>>::Stored>();
const _: () = assert_same_size::<usize, <usize as Backend<()>>::Stored>();
}
unsafe impl<T> Backend<T> for usize {
type Stored = *mut T;
fn get_ptr(s: Self::Stored) -> (*mut T, Self) {
(s, Strict::addr(s))
}
fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored {
Strict::with_addr(provenance, addr)
}
fn get_int(s: Self::Stored) -> Self {
Strict::addr(s)
}
}
#[cfg(target_pointer_width = "64")]
unsafe impl<T> Backend<T> for u64 {
type Stored = *mut T;
fn get_ptr(s: Self::Stored) -> (*mut T, Self) {
(s, Strict::addr(s) as u64)
}
fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored {
Strict::with_addr(provenance, addr as usize)
}
fn get_int(s: Self::Stored) -> Self {
Strict::addr(s) as u64
}
}
macro_rules! impl_backend_2_tuple {
(impl for $ty:ty { (*mut T, $int:ident), $num:expr }) => {
unsafe impl<T> Backend<T> for $ty {
type Stored = (*mut T, $int);
fn get_ptr(s: Self::Stored) -> (*mut T, Self) {
(s.0, Self::get_int(s))
}
fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored {
let ptr_addr = (addr >> $num) as usize;
let int_addr = addr as $int; (Strict::with_addr(provenance, ptr_addr), int_addr)
}
fn get_int(s: Self::Stored) -> Self {
let ptr_addr = Strict::addr(s.0) as $int;
(<$ty>::from(ptr_addr) << $num) | <$ty>::from(s.1)
}
}
};
}
#[cfg_attr(target_pointer_width = "64", allow(unused))] macro_rules! impl_backend_3_tuple {
(impl for $ty:ty { (*mut T, $int1:ident, $int2:ident), $num1:expr, $num2:expr }) => {
unsafe impl<T> Backend<T> for $ty {
type Stored = (*mut T, $int1, $int2);
fn get_ptr(s: Self::Stored) -> (*mut T, Self) {
(s.0, Self::get_int(s))
}
fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored {
let ptr_addr = (addr >> ($num1 + $num2)) as usize;
let num1_addr = (addr >> $num2) as $int1; let num2_addr = addr as $int2; (
Strict::with_addr(provenance, ptr_addr),
num1_addr,
num2_addr,
)
}
fn get_int(s: Self::Stored) -> Self {
let ptr_addr = Strict::addr(s.0) as $ty;
let num1_addr = s.1 as $ty;
let num2_addr = s.2 as $ty;
(ptr_addr << ($num1 + $num2)) | (num1_addr << ($num2)) | num2_addr
}
}
};
}
#[cfg(target_pointer_width = "64")]
impl_backend_2_tuple!(impl for u128 { (*mut T, u64), 64 });
#[cfg(target_pointer_width = "32")]
impl_backend_2_tuple!(impl for u64 { (*mut T, u32), 32 });
#[cfg(target_pointer_width = "32")]
impl_backend_3_tuple!(impl for u128 { (*mut T, u32, u64), 32, 64 });
#[cfg(target_pointer_width = "16")]
impl_backend_3_tuple!(impl for u64 { (*mut T, u16, u32), 16, 32 });