diff --git a/src/lib.rs b/src/lib.rs index 02702c8..8d43fbd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,13 +2,57 @@ #![warn(rust_2018_idioms)] #![deny(unsafe_op_in_unsafe_fn)] +pub mod ptr; mod strategy; pub use stuff::Backend; use crate::strategy::{SafeStrategyAdaptor, SafeStuffingStrategy}; -pub struct StuffedPtr(stuff::StuffedPtr, B>) +pub struct SafeStuffedPtr(stuff::StuffedPtr, B>) where S: SafeStuffingStrategy, - B: Backend; + B: Backend, + B: TryInto, + usize: TryInto; + +impl SafeStuffedPtr +where + S: SafeStuffingStrategy, + B: Backend, + B: TryInto, + usize: TryInto, +{ + 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 { + self.0.into_other() + } +} + +impl SafeStuffedPtr +where + S: SafeStuffingStrategy, + B: Backend, + B: TryInto, + usize: TryInto, + S::Other: Copy, +{ + pub fn copy_other(&self) -> Option { + self.0.copy_other() + } +} diff --git a/src/ptr.rs b/src/ptr.rs new file mode 100644 index 0000000..0d6433d --- /dev/null +++ b/src/ptr.rs @@ -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; + +impl sealed::Sealed for Mask1 {} + +unsafe impl PtrStuffingStrategy for Mask1 { + fn stuff_ptr(addr: usize) -> usize { + addr & MASK + } + + fn extract_ptr(addr: usize) -> usize { + addr & !MASK + } +} diff --git a/src/strategy.rs b/src/strategy.rs index aba4950..b005155 100644 --- a/src/strategy.rs +++ b/src/strategy.rs @@ -1,13 +1,13 @@ use core::marker::PhantomData; -use stuff::Backend; +use crate::ptr::PtrStuffingStrategy; pub trait SafeStuffingStrategy { - type Extra; + type Other; - fn stuff_extra(extra: &Self::Extra) -> B; + fn stuff_other(extra: &Self::Other) -> B; - fn extract_extra(addr: B) -> Option; + fn extract_other(addr: B) -> Option; } /// An internal type to convert from the safe to the unsafe trait @@ -19,28 +19,30 @@ pub(crate) struct SafeStrategyAdaptor(PhantomData); unsafe impl stuff::StuffingStrategy for SafeStrategyAdaptor where S: SafeStuffingStrategy, + B: TryInto, + usize: TryInto, { - type Extra = S::Extra; + type Other = S::Other; - fn is_extra(data: B) -> bool { - S::extract_extra(data).is_some() + fn is_other(data: B) -> bool { + S::extract_other(data).is_some() } - fn stuff_extra(inner: Self::Extra) -> B { - let b = S::stuff_extra(&inner); + fn stuff_other(inner: Self::Other) -> B { + let b = S::stuff_other(&inner); core::mem::forget(inner); b } - unsafe fn extract_extra(data: B) -> Self::Extra { - S::extract_extra(data).unwrap() + unsafe fn extract_other(data: B) -> Self::Other { + S::extract_other(data).unwrap() } fn stuff_ptr(addr: usize) -> B { - addr + addr.try_into().unwrap_or_else(|_| panic!()) } fn extract_ptr(inner: B) -> usize { - inner + inner.try_into().unwrap_or_else(|_| panic!()) } }