1use core::marker::PhantomData;
6use core::mem::MaybeUninit;
7use core::ops::{Deref, DerefMut};
8use core::ptr::slice_from_raw_parts_mut;
9use core::slice::from_raw_parts;
10
11use munge::{Destructure, Move, Restructure};
12use zerocopy::{FromBytes, IntoBytes};
13
14#[repr(transparent)]
20pub struct Slot<'de, T: ?Sized> {
21 ptr: *mut T,
22 _phantom: PhantomData<&'de mut [u8]>,
23}
24
25unsafe impl<T: Send> Send for Slot<'_, T> {}
26unsafe impl<T: Sync> Sync for Slot<'_, T> {}
27
28impl<'de, T: ?Sized> Slot<'de, T> {
29 pub fn new(backing: &'de mut MaybeUninit<T>) -> Self
31 where
32 T: Sized,
33 {
34 unsafe {
35 backing.as_mut_ptr().write_bytes(0, 1);
36 }
37 unsafe { Self::new_unchecked(backing.as_mut_ptr()) }
38 }
39
40 pub unsafe fn new_unchecked(ptr: *mut T) -> Self {
47 Self { ptr, _phantom: PhantomData }
48 }
49
50 pub fn as_mut(&mut self) -> Slot<'_, T> {
52 Self { ptr: self.ptr, _phantom: PhantomData }
53 }
54
55 pub fn as_mut_ptr(&mut self) -> *mut T {
57 self.ptr
58 }
59
60 pub fn as_ptr(&self) -> *const T {
62 self.ptr
63 }
64
65 pub unsafe fn deref_unchecked(&self) -> &T {
71 unsafe { &*self.as_ptr() }
72 }
73
74 pub unsafe fn deref_mut_unchecked(&mut self) -> &mut T {
80 unsafe { &mut *self.as_mut_ptr() }
81 }
82
83 pub fn write(&mut self, value: T)
85 where
86 T: IntoBytes + Sized,
87 {
88 unsafe {
89 self.as_mut_ptr().write(value);
90 }
91 }
92}
93
94impl<T> Slot<'_, T> {
95 pub fn as_bytes(&self) -> &[u8] {
97 unsafe { from_raw_parts(self.ptr.cast::<u8>(), size_of::<T>()) }
98 }
99}
100
101impl<T, const N: usize> Slot<'_, [T; N]> {
102 pub fn index(&mut self, index: usize) -> Slot<'_, T> {
104 assert!(index < N, "attempted to index out-of-bounds");
105
106 Slot { ptr: unsafe { self.as_mut_ptr().cast::<T>().add(index) }, _phantom: PhantomData }
107 }
108}
109
110impl<T> Slot<'_, [T]> {
111 pub unsafe fn new_slice_unchecked(ptr: *mut T, len: usize) -> Self {
118 Self { ptr: slice_from_raw_parts_mut(ptr, len), _phantom: PhantomData }
119 }
120
121 pub fn index(&mut self, index: usize) -> Slot<'_, T> {
123 assert!(index < self.ptr.len(), "attempted to index out-of-bounds");
124
125 Slot { ptr: unsafe { self.as_mut_ptr().cast::<T>().add(index) }, _phantom: PhantomData }
126 }
127}
128
129impl<T: FromBytes> Deref for Slot<'_, T> {
130 type Target = T;
131
132 fn deref(&self) -> &Self::Target {
133 unsafe { &*self.as_ptr() }
134 }
135}
136
137impl<T: FromBytes> DerefMut for Slot<'_, T> {
138 fn deref_mut(&mut self) -> &mut Self::Target {
139 unsafe { &mut *self.as_mut_ptr() }
140 }
141}
142
143impl<'de, T> Iterator for Slot<'de, [T]> {
144 type Item = Slot<'de, T>;
145
146 fn next(&mut self) -> Option<Self::Item> {
147 if self.ptr.len() == 0 {
148 return None;
149 }
150
151 let result = Slot { ptr: self.ptr.cast::<T>(), _phantom: PhantomData };
152
153 self.ptr =
154 slice_from_raw_parts_mut(unsafe { self.ptr.cast::<T>().add(1) }, self.ptr.len() - 1);
155
156 Some(result)
157 }
158}
159
160unsafe impl<T> Destructure for Slot<'_, T> {
161 type Underlying = T;
162 type Destructuring = Move;
163
164 fn underlying(&mut self) -> *mut Self::Underlying {
165 self.as_mut_ptr()
166 }
167}
168
169unsafe impl<'de, T, U: 'de> Restructure<U> for Slot<'de, T> {
170 type Restructured = Slot<'de, U>;
171
172 unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured {
173 Slot { ptr, _phantom: PhantomData }
174 }
175}