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 fn capacity(&self) -> u32 {
38 Data::SIZE
39 }
40
41 #[inline(always)]
42 #[track_caller]
43 unsafe fn set_size(&mut self, size: u32) {
44 debug_assert!(
45 size == 0 || size == Data::SIZE,
46 "`set_size` called with invalid input {size} (self size {})",
47 self.size()
48 );
49
50 unsafe {
52 self.size.write(size);
53 }
54 }
55
56 #[inline(always)]
57 #[track_caller]
58 unsafe fn from_ptr<'a>(
59 ptr: &'a NonNull<Self::PointerType>,
60 size: &'a u32,
61 capacity: u32,
62 ) -> impl Deref<Target = Self> + 'a {
63 debug_assert!(ptr.is_aligned(), "Misaligned pointer");
64 debug_assert!(
65 *size == 0 || *size <= capacity,
66 "Invalid size {size} for capacity {capacity}"
67 );
68 debug_assert!(
70 capacity == 0 || capacity >= Data::SIZE,
71 "Invalid capacity {capacity} for size {}",
72 Data::SIZE
73 );
74
75 let size = NonNull::from_ref(size);
76
77 DerefWrapper(MaybeData { data: *ptr, size })
78 }
79
80 #[inline(always)]
81 #[track_caller]
82 unsafe fn from_mut_ptr<'a>(
83 ptr: &'a mut NonNull<Self::PointerType>,
84 size: &'a mut u32,
85 capacity: u32,
86 ) -> impl DerefMut<Target = Self> + 'a {
87 debug_assert!(ptr.is_aligned(), "Misaligned pointer");
88 debug_assert!(
89 *size == 0 || *size <= capacity,
90 "Invalid size {size} for capacity {capacity}"
91 );
92 debug_assert!(
93 capacity >= Data::SIZE,
94 "Invalid capacity {capacity} for size {}",
95 Data::SIZE
96 );
97
98 DerefWrapper(MaybeData {
99 data: *ptr,
100 size: NonNull::from_mut(size),
101 })
102 }
103
104 #[inline(always)]
105 unsafe fn as_ptr(&self) -> impl Deref<Target = NonNull<Self::PointerType>> {
106 &self.data
107 }
108
109 #[inline(always)]
110 unsafe fn as_mut_ptr(&mut self) -> impl DerefMut<Target = NonNull<Self::PointerType>> {
111 &mut self.data
112 }
113}
114
115impl<Data> IoTypeOptional for MaybeData<Data> where Data: TrivialType {}
116
117impl<Data> MaybeData<Data>
118where
119 Data: TrivialType,
120{
121 pub const fn from_ref(data: Option<&'_ Data>) -> impl Deref<Target = Self> + '_ {
126 let (data, size) = if let Some(data) = data {
127 (NonNull::from_ref(data), &Data::SIZE)
128 } else {
129 (NonNull::dangling(), &0)
130 };
131
132 DerefWrapper(Self {
133 data,
134 size: NonNull::from_ref(size),
135 })
136 }
137
138 #[track_caller]
149 pub fn from_mut<'a>(
150 buffer: &'a mut Data,
151 size: &'a mut u32,
152 ) -> impl DerefMut<Target = Self> + 'a {
153 debug_assert!(
154 *size == 0 || *size == Data::SIZE,
155 "Invalid size {size} (self size {})",
156 Data::SIZE
157 );
158
159 DerefWrapper(Self {
160 data: NonNull::from_mut(buffer),
161 size: NonNull::from_mut(size),
162 })
163 }
164
165 #[track_caller]
175 pub fn from_uninit<'a>(
176 uninit: &'a mut MaybeUninit<Data>,
177 size: &'a mut u32,
178 ) -> impl DerefMut<Target = Self> + 'a {
179 debug_assert_eq!(*size, 0, "Invalid size");
180
181 DerefWrapper(Self {
182 data: NonNull::from_mut(uninit).cast::<Data>(),
183 size: NonNull::from_mut(size),
184 })
185 }
186
187 #[inline(always)]
189 pub const fn get(&self) -> Option<&Data> {
190 if unsafe { self.size.read() } == Data::SIZE {
192 Some(unsafe { self.data.as_ref() })
194 } else {
195 None
196 }
197 }
198
199 #[inline(always)]
201 pub fn get_mut(&mut self) -> Option<&mut Data> {
202 if unsafe { self.size.read() } == Data::SIZE {
204 Some(unsafe { self.data.as_mut() })
206 } else {
207 None
208 }
209 }
210
211 #[inline(always)]
213 pub fn replace(&mut self, data: Data) -> &mut Data {
214 unsafe {
216 self.size.write(Data::SIZE);
217 }
218 unsafe {
220 self.data.write(data);
221 self.data.as_mut()
222 }
223 }
224
225 #[inline(always)]
227 pub fn remove(&mut self) {
228 unsafe {
230 self.size.write(0);
231 }
232 }
233
234 #[inline(always)]
237 pub fn get_mut_or_init_with<Init>(&mut self, init: Init) -> &mut Data
238 where
239 Init: FnOnce(&mut MaybeUninit<Data>) -> &mut Data,
240 {
241 if unsafe { self.size.read() } == Data::SIZE {
243 unsafe { self.data.as_mut() }
245 } else {
246 let data = init(unsafe { self.data.as_uninit_mut() });
248 unsafe {
250 self.size.write(Data::SIZE);
251 }
252 data
253 }
254 }
255
256 #[inline(always)]
261 pub unsafe fn assume_init(&mut self) -> &mut Data {
262 unsafe {
264 self.size.write(Data::SIZE);
265 }
266 unsafe { self.data.as_mut() }
269 }
270}
271
272impl<Data> MaybeData<Data>
273where
274 Data: TrivialType + Default,
275{
276 #[inline(always)]
278 pub fn get_mut_or_default(&mut self) -> &mut Data {
279 self.get_mut_or_init_with(|data| data.write(Data::default()))
280 }
281}