mirror of
https://github.com/Noratrieb/stuff.git
synced 2026-01-15 00:45:08 +01:00
try to have a safer api around drops
This commit is contained in:
parent
041a4cd670
commit
6ce36d0506
5 changed files with 291 additions and 238 deletions
|
|
@ -6,7 +6,7 @@ use sptr::Strict;
|
|||
/// be implemented on `Copy` types like `usize`, `u64`, or `u128`. Note that the `Self` type here
|
||||
/// serves as the main interchange format between the `Backend` and [`StuffedPtr`](`crate::StuffedPtr`)
|
||||
/// but *not* the actual underlying storage, which always contains a pointer to keep provenance
|
||||
/// (for example `(*mut T, u32)` on 32 bit for `u64`). This implies that `Self` *should* have the same
|
||||
/// (for example `(*mut (), u32)` on 32 bit for `u64`). This implies that `Self` *should* have the same
|
||||
/// size as `Backend::Stored`.
|
||||
///
|
||||
/// This trait is just exposed for convenience and flexibility, you are usually not expected to implement
|
||||
|
|
@ -16,7 +16,7 @@ use sptr::Strict;
|
|||
/// # Safety
|
||||
/// Implementers of this trait *must* keep provenance of pointers, so if a valid pointer address+provenance
|
||||
/// combination is set in `set_ptr`, `get_ptr` *must* return the exact same values and provenance.
|
||||
pub unsafe trait Backend<T> {
|
||||
pub unsafe trait Backend {
|
||||
/// The underlying type where the data is stored. Often a tuple of a pointer (for the provenance)
|
||||
/// and some integers to fill up the bytes.
|
||||
type Stored: Copy;
|
||||
|
|
@ -25,11 +25,11 @@ pub unsafe trait Backend<T> {
|
|||
/// is able to use the full bytes to pack in the pointer address, the full address is returned
|
||||
/// in the second tuple field, as the integer. The provenance of the pointer is returned as
|
||||
/// the first tuple field, but its address should be ignored and may be invalid.
|
||||
fn get_ptr(s: Self::Stored) -> (*mut T, Self);
|
||||
fn get_ptr(s: Self::Stored) -> (*mut (), Self);
|
||||
|
||||
/// Set a new pointer address. The provenance of the new pointer is transferred in the first argument,
|
||||
/// and the address in the second. See [`Backend::get_ptr`] for more details on the separation.
|
||||
fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored;
|
||||
fn set_ptr(provenance: *mut (), addr: Self) -> Self::Stored;
|
||||
|
||||
/// Get the integer value from the backend. Note that this *must not* be used to create a pointer,
|
||||
/// for that use [`Backend::get_ptr`] to keep the provenance.
|
||||
|
|
@ -49,19 +49,19 @@ mod backend_size_asserts {
|
|||
}
|
||||
|
||||
#[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>();
|
||||
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;
|
||||
unsafe impl Backend for usize {
|
||||
type Stored = *mut ();
|
||||
|
||||
fn get_ptr(s: Self::Stored) -> (*mut T, Self) {
|
||||
fn get_ptr(s: Self::Stored) -> (*mut (), Self) {
|
||||
(s, Strict::addr(s))
|
||||
}
|
||||
|
||||
fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored {
|
||||
fn set_ptr(provenance: *mut (), addr: Self) -> Self::Stored {
|
||||
Strict::with_addr(provenance, addr)
|
||||
}
|
||||
|
||||
|
|
@ -72,14 +72,14 @@ unsafe impl<T> Backend<T> for usize {
|
|||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
/// on 64 bit, we can just treat u64/usize interchangeably, because uintptr_t == size_t in Rust
|
||||
unsafe impl<T> Backend<T> for u64 {
|
||||
type Stored = *mut T;
|
||||
unsafe impl Backend for u64 {
|
||||
type Stored = *mut ();
|
||||
|
||||
fn get_ptr(s: Self::Stored) -> (*mut T, Self) {
|
||||
fn get_ptr(s: Self::Stored) -> (*mut (), Self) {
|
||||
(s, Strict::addr(s) as u64)
|
||||
}
|
||||
|
||||
fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored {
|
||||
fn set_ptr(provenance: *mut (), addr: Self) -> Self::Stored {
|
||||
Strict::with_addr(provenance, addr as usize)
|
||||
}
|
||||
|
||||
|
|
@ -89,17 +89,17 @@ unsafe impl<T> Backend<T> for u64 {
|
|||
}
|
||||
|
||||
macro_rules! impl_backend_2_tuple {
|
||||
(impl for $ty:ty { (*mut T, $int:ident), $num:expr }) => {
|
||||
unsafe impl<T> Backend<T> for $ty {
|
||||
(impl for $ty:ty { (*mut (), $int:ident), $num:expr }) => {
|
||||
unsafe impl Backend for $ty {
|
||||
// this one keeps the MSB in the pointer address, and the LSB in the integer
|
||||
|
||||
type Stored = (*mut T, $int);
|
||||
type Stored = (*mut (), $int);
|
||||
|
||||
fn get_ptr(s: Self::Stored) -> (*mut T, Self) {
|
||||
fn get_ptr(s: Self::Stored) -> (*mut (), Self) {
|
||||
(s.0, Self::get_int(s))
|
||||
}
|
||||
|
||||
fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored {
|
||||
fn set_ptr(provenance: *mut (), addr: Self) -> Self::Stored {
|
||||
let ptr_addr = (addr >> $num) as usize;
|
||||
let int_addr = addr as $int; // truncate it
|
||||
(Strict::with_addr(provenance, ptr_addr), int_addr)
|
||||
|
|
@ -116,17 +116,17 @@ macro_rules! impl_backend_2_tuple {
|
|||
/// num1 is ptr-sized, num2 is 2*ptr sized
|
||||
#[cfg_attr(target_pointer_width = "64", allow(unused))] // not required on 64 bit
|
||||
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 {
|
||||
(impl for $ty:ty { (*mut (), $int1:ident, $int2:ident), $num1:expr, $num2:expr }) => {
|
||||
unsafe impl Backend for $ty {
|
||||
// this one keeps the MSB in the pointer address, ISB in int1 and the LSB in the int2
|
||||
|
||||
type Stored = (*mut T, $int1, $int2);
|
||||
type Stored = (*mut (), $int1, $int2);
|
||||
|
||||
fn get_ptr(s: Self::Stored) -> (*mut T, Self) {
|
||||
fn get_ptr(s: Self::Stored) -> (*mut (), Self) {
|
||||
(s.0, Self::get_int(s))
|
||||
}
|
||||
|
||||
fn set_ptr(provenance: *mut T, addr: Self) -> Self::Stored {
|
||||
fn set_ptr(provenance: *mut (), addr: Self) -> Self::Stored {
|
||||
let ptr_addr = (addr >> ($num1 + $num2)) as usize;
|
||||
let num1_addr = (addr >> $num2) as $int1; // truncate it
|
||||
let num2_addr = addr as $int2; // truncate it
|
||||
|
|
@ -148,15 +148,15 @@ macro_rules! impl_backend_3_tuple {
|
|||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
impl_backend_2_tuple!(impl for u128 { (*mut T, u64), 64 });
|
||||
impl_backend_2_tuple!(impl for u128 { (*mut (), u64), 64 });
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
impl_backend_2_tuple!(impl for u64 { (*mut T, u32), 32 });
|
||||
impl_backend_2_tuple!(impl for u64 { (*mut (), u32), 32 });
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
impl_backend_3_tuple!(impl for u128 { (*mut T, u32, u64), 32, 64 });
|
||||
impl_backend_3_tuple!(impl for u128 { (*mut (), u32, u64), 32, 64 });
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
impl_backend_3_tuple!(impl for u64 { (*mut T, u16, u32), 16, 32 });
|
||||
impl_backend_3_tuple!(impl for u64 { (*mut (), u16, u32), 16, 32 });
|
||||
|
||||
// no 128 on 16 bit for now
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue