bad things, ignore pls

This commit is contained in:
nora 2022-04-06 21:27:27 +02:00
parent 83f4ce6f51
commit fc2325731e
3 changed files with 99 additions and 15 deletions

View file

@ -2,13 +2,57 @@
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]
#![deny(unsafe_op_in_unsafe_fn)] #![deny(unsafe_op_in_unsafe_fn)]
pub mod ptr;
mod strategy; mod strategy;
pub use stuff::Backend; pub use stuff::Backend;
use crate::strategy::{SafeStrategyAdaptor, SafeStuffingStrategy}; use crate::strategy::{SafeStrategyAdaptor, SafeStuffingStrategy};
pub struct StuffedPtr<T, S, B = usize>(stuff::StuffedPtr<T, SafeStrategyAdaptor<S>, B>) pub struct SafeStuffedPtr<T, S, B = usize>(stuff::StuffedPtr<T, SafeStrategyAdaptor<S>, B>)
where where
S: SafeStuffingStrategy<B>, S: SafeStuffingStrategy<B>,
B: Backend<T>; B: Backend<T>,
B: TryInto<usize>,
usize: TryInto<B>;
impl<T, S, B> SafeStuffedPtr<T, S, B>
where
S: SafeStuffingStrategy<B>,
B: Backend<T>,
B: TryInto<usize>,
usize: TryInto<B>,
{
pub fn new_ptr(ptr: *mut T) -> Self {
Self(stuff::StuffedPtr::new_ptr(ptr))
}
pub fn new_extra(ptr: *mut T) -> Self {
Self(stuff::StuffedPtr::new_ptr(ptr))
}
pub fn get_ptr(&self) -> Option<*const T> {
self.0.get_ptr().map(|ptr| ptr as *const _)
}
pub fn get_mut_ptr(&mut self) -> Option<*mut T> {
self.0.get_ptr()
}
pub fn into_other(self) -> Option<S::Other> {
self.0.into_other()
}
}
impl<T, S, B> SafeStuffedPtr<T, S, B>
where
S: SafeStuffingStrategy<B>,
B: Backend<T>,
B: TryInto<usize>,
usize: TryInto<B>,
S::Other: Copy,
{
pub fn copy_other(&self) -> Option<S::Other> {
self.0.copy_other()
}
}

38
src/ptr.rs Normal file
View file

@ -0,0 +1,38 @@
/// # Safety
/// Same invariants as [`stuff::StuffingStrategy]
pub unsafe trait PtrStuffingStrategy: sealed::Sealed {
fn stuff_ptr(addr: usize) -> usize;
fn extract_ptr(addr: usize) -> usize;
}
mod sealed {
pub trait Sealed {}
}
pub struct Identity;
impl sealed::Sealed for Identity {}
unsafe impl PtrStuffingStrategy for Identity {
fn stuff_ptr(addr: usize) -> usize {
addr
}
fn extract_ptr(addr: usize) -> usize {
addr
}
}
pub struct Mask1<const MASK: usize>;
impl<const MASK: usize> sealed::Sealed for Mask1<MASK> {}
unsafe impl<const MASK: usize> PtrStuffingStrategy for Mask1<MASK> {
fn stuff_ptr(addr: usize) -> usize {
addr & MASK
}
fn extract_ptr(addr: usize) -> usize {
addr & !MASK
}
}

View file

@ -1,13 +1,13 @@
use core::marker::PhantomData; use core::marker::PhantomData;
use stuff::Backend; use crate::ptr::PtrStuffingStrategy;
pub trait SafeStuffingStrategy<B> { pub trait SafeStuffingStrategy<B> {
type Extra; type Other;
fn stuff_extra(extra: &Self::Extra) -> B; fn stuff_other(extra: &Self::Other) -> B;
fn extract_extra(addr: B) -> Option<Self::Extra>; fn extract_other(addr: B) -> Option<Self::Other>;
} }
/// An internal type to convert from the safe to the unsafe trait /// An internal type to convert from the safe to the unsafe trait
@ -19,28 +19,30 @@ pub(crate) struct SafeStrategyAdaptor<S>(PhantomData<S>);
unsafe impl<S, B> stuff::StuffingStrategy<B> for SafeStrategyAdaptor<S> unsafe impl<S, B> stuff::StuffingStrategy<B> for SafeStrategyAdaptor<S>
where where
S: SafeStuffingStrategy<B>, S: SafeStuffingStrategy<B>,
B: TryInto<usize>,
usize: TryInto<B>,
{ {
type Extra = S::Extra; type Other = S::Other;
fn is_extra(data: B) -> bool { fn is_other(data: B) -> bool {
S::extract_extra(data).is_some() S::extract_other(data).is_some()
} }
fn stuff_extra(inner: Self::Extra) -> B { fn stuff_other(inner: Self::Other) -> B {
let b = S::stuff_extra(&inner); let b = S::stuff_other(&inner);
core::mem::forget(inner); core::mem::forget(inner);
b b
} }
unsafe fn extract_extra(data: B) -> Self::Extra { unsafe fn extract_other(data: B) -> Self::Other {
S::extract_extra(data).unwrap() S::extract_other(data).unwrap()
} }
fn stuff_ptr(addr: usize) -> B { fn stuff_ptr(addr: usize) -> B {
addr addr.try_into().unwrap_or_else(|_| panic!())
} }
fn extract_ptr(inner: B) -> usize { fn extract_ptr(inner: B) -> usize {
inner inner.try_into().unwrap_or_else(|_| panic!())
} }
} }