1use crate::trivial_type::TrivialType;
2use crate::{DerefWrapper, IoType, IoTypeOptional};
3use core::mem::MaybeUninit;
4use core::ops::{Deref, DerefMut};
5use core::ptr::NonNull;
6
7#[derive(Debug)]
13pub struct MaybeData<Data>
14where
15 Data: TrivialType,
16{
17 data: NonNull<Data>,
18 size: NonNull<u32>,
19}
20
21unsafe impl<Data> IoType for MaybeData<Data>
23where
24 Data: TrivialType,
25{
26 const METADATA: &[u8] = Data::METADATA;
27
28 type PointerType = Data;
29
30 #[inline(always)]
31 fn size(&self) -> u32 {
32 unsafe { self.size.read() }
34 }
35
36 #[inline(always)]
37 unsafe fn size_ptr(&self) -> impl Deref<Target = NonNull<u32>> {
38 DerefWrapper(self.size)
39 }
40
41 #[inline(always)]
42 unsafe fn size_mut_ptr(&mut self) -> impl DerefMut<Target = *mut u32> {
43 DerefWrapper(self.size.as_ptr())
44 }
45
46 #[inline(always)]
47 fn capacity(&self) -> u32 {
48 Data::SIZE
49 }
50
51 #[inline(always)]
52 unsafe fn capacity_ptr(&self) -> impl Deref<Target = NonNull<u32>> {
53 DerefWrapper(NonNull::from_ref(&Data::SIZE))
54 }
55
56 #[inline(always)]
57 #[track_caller]
58 unsafe fn set_size(&mut self, size: u32) {
59 debug_assert!(
60 size == 0 || size == self.size(),
61 "`set_size` called with invalid input {size} (self size {})",
62 self.size()
63 );
64
65 unsafe {
67 self.size.write(size);
68 }
69 }
70
71 #[inline(always)]
72 #[track_caller]
73 unsafe fn from_ptr<'a>(
74 data: &'a NonNull<Self::PointerType>,
75 size: &'a u32,
76 capacity: u32,
77 ) -> impl Deref<Target = Self> + 'a {
78 debug_assert!(data.is_aligned(), "Misaligned pointer");
79 debug_assert!(
80 *size == 0 || *size <= capacity,
81 "Invalid size {size} for capacity {capacity}"
82 );
83 debug_assert!(
85 capacity == 0 || capacity >= Data::SIZE,
86 "Invalid capacity {capacity} for size {}",
87 Data::SIZE
88 );
89
90 let size = NonNull::from_ref(size);
91
92 DerefWrapper(MaybeData { data: *data, size })
93 }
94
95 #[inline(always)]
96 #[track_caller]
97 unsafe fn from_mut_ptr<'a>(
98 data: &'a mut NonNull<Self::PointerType>,
99 size: &'a mut *mut u32,
100 capacity: u32,
101 ) -> impl DerefMut<Target = Self> + 'a {
102 debug_assert!(!size.is_null(), "`null` pointer for non-`TrivialType` size");
103 let size = unsafe { NonNull::new_unchecked(*size) };
105 debug_assert!(data.is_aligned(), "Misaligned pointer");
106 {
107 let size = unsafe { size.read() };
109 debug_assert!(
110 size == 0 || size <= capacity,
111 "Invalid size {size} for capacity {capacity}"
112 );
113 }
114 debug_assert!(
115 capacity >= Data::SIZE,
116 "Invalid capacity {capacity} for size {}",
117 Data::SIZE
118 );
119
120 DerefWrapper(MaybeData { data: *data, size })
121 }
122
123 #[inline(always)]
124 unsafe fn as_ptr(&self) -> impl Deref<Target = NonNull<Self::PointerType>> {
125 &self.data
126 }
127
128 #[inline(always)]
129 unsafe fn as_mut_ptr(&mut self) -> impl DerefMut<Target = NonNull<Self::PointerType>> {
130 &mut self.data
131 }
132}
133
134impl<Data> IoTypeOptional for MaybeData<Data> where Data: TrivialType {}
135
136impl<Data> MaybeData<Data>
137where
138 Data: TrivialType,
139{
140 pub const fn from_ref(data: Option<&'_ Data>) -> impl Deref<Target = Self> + '_ {
145 let (data, size) = if let Some(data) = data {
146 (NonNull::from_ref(data), &Data::SIZE)
147 } else {
148 (NonNull::dangling(), &0)
149 };
150
151 DerefWrapper(Self {
152 data,
153 size: NonNull::from_ref(size),
154 })
155 }
156
157 #[track_caller]
168 pub fn from_mut<'a>(
169 buffer: &'a mut Data,
170 size: &'a mut u32,
171 ) -> impl DerefMut<Target = Self> + 'a {
172 debug_assert!(
173 *size == 0 || *size == Data::SIZE,
174 "Invalid size {size} (self size {})",
175 Data::SIZE
176 );
177
178 DerefWrapper(Self {
179 data: NonNull::from_mut(buffer),
180 size: NonNull::from_ref(size),
181 })
182 }
183
184 #[track_caller]
196 pub fn from_uninit<'a>(
197 uninit: &'a mut MaybeUninit<Data>,
198 size: &'a mut u32,
199 ) -> impl DerefMut<Target = Self> + 'a {
200 debug_assert_eq!(*size, 0, "Invalid size");
201
202 DerefWrapper(Self {
203 data: NonNull::from_mut(uninit).cast::<Data>(),
204 size: NonNull::from_mut(size),
205 })
206 }
207
208 #[inline(always)]
210 pub const fn get(&self) -> Option<&Data> {
211 if unsafe { self.size.read() } == Data::SIZE {
213 Some(unsafe { self.data.as_ref() })
215 } else {
216 None
217 }
218 }
219
220 #[inline(always)]
222 pub fn get_mut(&mut self) -> Option<&mut Data> {
223 if unsafe { self.size.read() } == Data::SIZE {
225 Some(unsafe { self.data.as_mut() })
227 } else {
228 None
229 }
230 }
231
232 #[inline(always)]
234 pub fn replace(&mut self, data: Data) -> &mut Data {
235 unsafe {
237 self.size.write(Data::SIZE);
238 }
239 unsafe {
241 self.data.write(data);
242 self.data.as_mut()
243 }
244 }
245
246 #[inline(always)]
248 pub fn remove(&mut self) {
249 unsafe {
251 self.size.write(0);
252 }
253 }
254
255 #[inline(always)]
258 pub fn get_mut_or_init_with<Init>(&mut self, init: Init) -> &mut Data
259 where
260 Init: FnOnce(&mut MaybeUninit<Data>) -> &mut Data,
261 {
262 if unsafe { self.size.read() } == Data::SIZE {
264 unsafe { self.data.as_mut() }
266 } else {
267 let data = init(unsafe { self.data.as_uninit_mut() });
269 unsafe {
271 self.size.write(Data::SIZE);
272 }
273 data
274 }
275 }
276
277 #[inline(always)]
282 pub unsafe fn assume_init(&mut self) -> &mut Data {
283 unsafe {
285 self.size.write(Data::SIZE);
286 }
287 unsafe { self.data.as_mut() }
290 }
291}
292
293impl<Data> MaybeData<Data>
294where
295 Data: TrivialType + Default,
296{
297 #[inline(always)]
299 pub fn get_mut_or_default(&mut self) -> &mut Data {
300 self.get_mut_or_init_with(|data| data.write(Data::default()))
301 }
302}