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 data: &'a NonNull<Self::PointerType>,
60 size: &'a u32,
61 capacity: u32,
62 ) -> impl Deref<Target = Self> + 'a {
63 debug_assert!(data.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: *data, size })
78 }
79
80 #[inline(always)]
81 #[track_caller]
82 unsafe fn from_mut_ptr<'a>(
83 data: &'a mut NonNull<Self::PointerType>,
84 size: &'a mut u32,
85 capacity: u32,
86 ) -> impl DerefMut<Target = Self> + 'a {
87 debug_assert!(data.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: *data,
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]
177 pub fn from_uninit<'a>(
178 uninit: &'a mut MaybeUninit<Data>,
179 size: &'a mut u32,
180 ) -> impl DerefMut<Target = Self> + 'a {
181 debug_assert_eq!(*size, 0, "Invalid size");
182
183 DerefWrapper(Self {
184 data: NonNull::from_mut(uninit).cast::<Data>(),
185 size: NonNull::from_mut(size),
186 })
187 }
188
189 #[inline(always)]
191 pub const fn get(&self) -> Option<&Data> {
192 if unsafe { self.size.read() } == Data::SIZE {
194 Some(unsafe { self.data.as_ref() })
196 } else {
197 None
198 }
199 }
200
201 #[inline(always)]
203 pub fn get_mut(&mut self) -> Option<&mut Data> {
204 if unsafe { self.size.read() } == Data::SIZE {
206 Some(unsafe { self.data.as_mut() })
208 } else {
209 None
210 }
211 }
212
213 #[inline(always)]
215 pub fn replace(&mut self, data: Data) -> &mut Data {
216 unsafe {
218 self.size.write(Data::SIZE);
219 }
220 unsafe {
222 self.data.write(data);
223 self.data.as_mut()
224 }
225 }
226
227 #[inline(always)]
229 pub fn remove(&mut self) {
230 unsafe {
232 self.size.write(0);
233 }
234 }
235
236 #[inline(always)]
239 pub fn get_mut_or_init_with<Init>(&mut self, init: Init) -> &mut Data
240 where
241 Init: FnOnce(&mut MaybeUninit<Data>) -> &mut Data,
242 {
243 if unsafe { self.size.read() } == Data::SIZE {
245 unsafe { self.data.as_mut() }
247 } else {
248 let data = init(unsafe { self.data.as_uninit_mut() });
250 unsafe {
252 self.size.write(Data::SIZE);
253 }
254 data
255 }
256 }
257
258 #[inline(always)]
263 pub unsafe fn assume_init(&mut self) -> &mut Data {
264 unsafe {
266 self.size.write(Data::SIZE);
267 }
268 unsafe { self.data.as_mut() }
271 }
272}
273
274impl<Data> MaybeData<Data>
275where
276 Data: TrivialType + Default,
277{
278 #[inline(always)]
280 pub fn get_mut_or_default(&mut self) -> &mut Data {
281 self.get_mut_or_init_with(|data| data.write(Data::default()))
282 }
283}