devela/data/dst/
helpers.rsuse crate::{
MaybeUninit, MemPod,
_core::{ptr, slice},
};
type BufSlice<T> = [MaybeUninit<T>];
pub(crate) fn decompose_pointer<T: ?Sized>(mut ptr: *const T) -> (*const (), usize, [usize; 3]) {
let addr = ptr as *const ();
let rv = mem_as_slice(&mut ptr);
let mut vals = [0; 3];
assert!(rv[0] == addr as usize, "BUG: Pointer layout is not (data_ptr, info...)");
vals[..rv.len() - 1].copy_from_slice(&rv[1..]);
(addr, rv.len() - 1, vals)
}
pub(crate) const fn mem_as_slice<T>(ptr: &mut T) -> &mut [usize] {
assert!(size_of::<T>() % size_of::<usize>() == 0);
assert!(align_of::<T>() % align_of::<usize>() == 0);
let words = size_of::<T>() / size_of::<usize>();
unsafe { slice::from_raw_parts_mut(ptr as *mut _ as *mut usize, words) }
}
pub(crate) unsafe fn make_fat_ptr<T: ?Sized, W: MemPod>(
data_ptr: *mut (),
meta_vals: &BufSlice<W>,
) -> *mut T {
#[repr(C)]
#[derive(Clone, Copy)]
struct Raw {
ptr: *const (),
meta: [usize; 4],
}
#[repr(C)]
union Inner<T: ?Sized> {
ptr: *mut T,
raw: Raw,
}
let mut rv = Inner { raw: Raw { ptr: data_ptr, meta: [0; 4] } };
assert!(meta_vals.len() * size_of::<W>() % size_of::<usize>() == 0);
assert!(meta_vals.len() * size_of::<W>() <= 4 * size_of::<usize>());
unsafe {
ptr::copy(
meta_vals.as_ptr() as *const u8,
rv.raw.meta.as_mut_ptr() as *mut u8,
meta_vals.len() * size_of::<W>(),
);
}
let rv = unsafe { rv.ptr };
assert_eq!(rv as *const (), data_ptr.cast_const());
rv
}
pub(crate) fn store_metadata<W: MemPod>(dst: &mut BufSlice<W>, meta_words: &[usize]) {
let n_bytes = size_of_val(meta_words);
assert!(
n_bytes <= dst.len() * size_of::<W>(),
"nbytes [{}] <= dst.len() [{}] * sizeof [{}]",
n_bytes,
dst.len(),
size_of::<W>()
);
unsafe {
ptr::copy(meta_words.as_ptr() as *const u8, dst.as_mut_ptr() as *mut u8, n_bytes);
}
}
pub(crate) const fn round_to_words<T>(len: usize) -> usize {
len.div_ceil(size_of::<T>())
}
pub(crate) fn check_fat_pointer<U, T: ?Sized>(v: &U, get_ref: impl FnOnce(&U) -> &T) -> &T {
let ptr: &T = get_ref(v);
assert_eq!(
ptr as *const _ as *const u8, v as *const _ as *const u8,
"MISUSE: Closure returned different pointer"
);
assert_eq!(size_of_val(ptr), size_of::<U>(), "MISUSE: Closure returned a subset pointer");
ptr
}
pub(crate) unsafe fn list_push_gen<T, W: MemPod>(
meta: &mut BufSlice<W>,
data: &mut BufSlice<W>,
count: usize,
mut gen: impl FnMut(usize) -> T,
reset_slot: &mut usize,
reset_value: usize,
) {
struct PanicState<'a, T>(*mut T, usize, &'a mut usize, usize);
impl<T> core::ops::Drop for PanicState<'_, T> {
fn drop(&mut self) {
if self.0.is_null() {
return;
}
*self.2 = self.3;
unsafe {
while self.1 != 0 {
ptr::drop_in_place(&mut *self.0);
ptr::write_bytes(self.0 as *mut u8, 0, size_of::<T>());
self.0 = self.0.offset(1);
self.1 -= 1;
}
}
}
}
let mut ptr = data.as_mut_ptr() as *mut T;
let mut clr = PanicState(ptr, 0, reset_slot, reset_value);
for i in 0..count {
let val = gen(i);
unsafe {
ptr::write(ptr, val);
}
ptr = unsafe { ptr.offset(1) };
clr.1 += 1;
}
clr.0 = ptr::null_mut();
store_metadata(meta, &[count]);
}