use core::convert::TryInto;
use crate::Backend;
pub unsafe trait StuffingStrategy<B> {
type Other;
fn is_other(data: B) -> bool;
fn stuff_other(inner: Self::Other) -> B;
unsafe fn extract_other(data: B) -> Self::Other;
fn stuff_ptr(addr: usize) -> B;
fn extract_ptr(inner: B) -> usize;
}
unsafe impl<B> StuffingStrategy<B> for ()
where
B: Backend<()> + Default + TryInto<usize>,
usize: TryInto<B>,
{
type Other = ();
fn is_other(_data: B) -> bool {
false
}
fn stuff_other(_inner: Self::Other) -> B {
B::default()
}
unsafe fn extract_other(_data: B) -> Self::Other {}
fn stuff_ptr(addr: usize) -> B {
addr.try_into()
.unwrap_or_else(|_| panic!("Address in `stuff_ptr` too big"))
}
fn extract_ptr(inner: B) -> usize {
inner
.try_into()
.unwrap_or_else(|_| panic!("Pointer value too big for usize"))
}
}
#[cfg(test)]
pub(crate) mod test_strategies {
use core::fmt::{Debug, Formatter};
use super::StuffingStrategy;
macro_rules! impl_usize_max_zst {
($ty:ident) => {
unsafe impl StuffingStrategy<usize> for $ty {
type Other = Self;
fn is_other(data: usize) -> bool {
data == usize::MAX
}
#[allow(clippy::forget_copy)]
fn stuff_other(inner: Self::Other) -> usize {
core::mem::forget(inner);
usize::MAX
}
unsafe fn extract_other(_data: usize) -> Self::Other {
$ty
}
fn stuff_ptr(addr: usize) -> usize {
addr
}
fn extract_ptr(inner: usize) -> usize {
inner
}
}
unsafe impl StuffingStrategy<u64> for $ty {
type Other = Self;
fn is_other(data: u64) -> bool {
data == u64::MAX
}
#[allow(clippy::forget_copy)]
fn stuff_other(inner: Self::Other) -> u64 {
core::mem::forget(inner);
u64::MAX
}
unsafe fn extract_other(_data: u64) -> Self::Other {
$ty
}
fn stuff_ptr(addr: usize) -> u64 {
addr as u64
}
fn extract_ptr(inner: u64) -> usize {
inner as usize
}
}
unsafe impl StuffingStrategy<u128> for $ty {
type Other = Self;
fn is_other(data: u128) -> bool {
data == u128::MAX
}
#[allow(clippy::forget_copy)]
fn stuff_other(inner: Self::Other) -> u128 {
core::mem::forget(inner);
u128::MAX
}
unsafe fn extract_other(_data: u128) -> Self::Other {
$ty
}
fn stuff_ptr(addr: usize) -> u128 {
addr as u128
}
fn extract_ptr(inner: u128) -> usize {
inner as usize
}
}
};
}
#[derive(Clone, Copy)]
pub struct EmptyInMax;
impl_usize_max_zst!(EmptyInMax);
pub struct HasDebug;
impl Debug for HasDebug {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.write_str("hello!")
}
}
impl_usize_max_zst!(HasDebug);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PanicsInDrop;
impl Drop for PanicsInDrop {
fn drop(&mut self) {
panic!("oh no!!!");
}
}
impl_usize_max_zst!(PanicsInDrop);
}