devela/data/dst/
helpers.rs
1use crate::{
4 MaybeUninit, MemPod,
5 _core::{ptr, slice},
6};
7
8type BufSlice<T> = [MaybeUninit<T>];
9
10pub(crate) fn decompose_pointer<T: ?Sized>(mut ptr: *const T) -> (*const (), usize, [usize; 3]) {
11 let addr = ptr as *const ();
12 let rv = mem_as_slice(&mut ptr);
13 let mut vals = [0; 3];
14 assert!(rv[0] == addr as usize, "BUG: Pointer layout is not (data_ptr, info...)");
15 vals[..rv.len() - 1].copy_from_slice(&rv[1..]);
16 (addr, rv.len() - 1, vals)
17}
18
19pub(crate) const fn mem_as_slice<T>(ptr: &mut T) -> &mut [usize] {
20 assert!(size_of::<T>() % size_of::<usize>() == 0);
21 assert!(align_of::<T>() % align_of::<usize>() == 0);
22 let words = size_of::<T>() / size_of::<usize>();
23 unsafe { slice::from_raw_parts_mut(ptr as *mut _ as *mut usize, words) }
25}
26
27pub(crate) unsafe fn make_fat_ptr<T: ?Sized, W: MemPod>(
29 data_ptr: *mut (),
30 meta_vals: &BufSlice<W>,
31) -> *mut T {
32 #[repr(C)]
33 #[derive(Clone, Copy)]
34 struct Raw {
35 ptr: *const (),
36 meta: [usize; 4],
37 }
38 #[repr(C)]
39 union Inner<T: ?Sized> {
40 ptr: *mut T,
41 raw: Raw,
42 }
43 let mut rv = Inner { raw: Raw { ptr: data_ptr, meta: [0; 4] } };
44 assert!(meta_vals.len() * size_of::<W>() % size_of::<usize>() == 0);
45 assert!(meta_vals.len() * size_of::<W>() <= 4 * size_of::<usize>());
46 unsafe {
48 ptr::copy(
49 meta_vals.as_ptr() as *const u8,
50 rv.raw.meta.as_mut_ptr() as *mut u8,
51 meta_vals.len() * size_of::<W>(),
52 );
53 }
54 let rv = unsafe { rv.ptr };
57 assert_eq!(rv as *const (), data_ptr.cast_const());
58 rv
59}
60
61pub(crate) fn store_metadata<W: MemPod>(dst: &mut BufSlice<W>, meta_words: &[usize]) {
63 let n_bytes = size_of_val(meta_words);
64 assert!(
65 n_bytes <= dst.len() * size_of::<W>(),
66 "nbytes [{}] <= dst.len() [{}] * sizeof [{}]",
67 n_bytes,
68 dst.len(),
69 size_of::<W>()
70 );
71 unsafe {
72 ptr::copy(meta_words.as_ptr() as *const u8, dst.as_mut_ptr() as *mut u8, n_bytes);
73 }
74}
75
76pub(crate) const fn round_to_words<T>(len: usize) -> usize {
77 len.div_ceil(size_of::<T>())
78}
79
80pub(crate) fn check_fat_pointer<U, T: ?Sized>(v: &U, get_ref: impl FnOnce(&U) -> &T) -> &T {
83 let ptr: &T = get_ref(v);
84 assert_eq!(
85 ptr as *const _ as *const u8, v as *const _ as *const u8,
86 "MISUSE: Closure returned different pointer"
87 );
88 assert_eq!(size_of_val(ptr), size_of::<U>(), "MISUSE: Closure returned a subset pointer");
89 ptr
90}
91
92pub(crate) unsafe fn list_push_gen<T, W: MemPod>(
102 meta: &mut BufSlice<W>,
103 data: &mut BufSlice<W>,
104 count: usize,
105 mut make: impl FnMut(usize) -> T,
106 reset_slot: &mut usize,
107 reset_value: usize,
108) {
109 struct PanicState<'a, T>(*mut T, usize, &'a mut usize, usize);
111 impl<T> core::ops::Drop for PanicState<'_, T> {
112 fn drop(&mut self) {
113 if self.0.is_null() {
114 return;
115 }
116 *self.2 = self.3;
118 unsafe {
120 while self.1 != 0 {
121 ptr::drop_in_place(&mut *self.0);
122 ptr::write_bytes(self.0 as *mut u8, 0, size_of::<T>());
123 self.0 = self.0.offset(1);
124 self.1 -= 1;
125 }
126 }
127 }
128 }
129
130 let mut ptr = data.as_mut_ptr() as *mut T;
131 let mut clr = PanicState(ptr, 0, reset_slot, reset_value);
132 for i in 0..count {
133 let val = make(i);
134 unsafe {
136 ptr::write(ptr, val);
137 }
138 ptr = unsafe { ptr.offset(1) };
140 clr.1 += 1;
141 }
142 clr.0 = ptr::null_mut();
144 store_metadata(meta, &[count]);
146}