ab_contracts_io_type/
maybe_data.rs1use 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>
22where
23 Data: TrivialType,
24{
25 const METADATA: &[u8] = Data::METADATA;
26
27 type PointerType = Data;
28
29 #[inline(always)]
30 fn size(&self) -> u32 {
31 unsafe { self.size.read() }
33 }
34
35 #[inline(always)]
36 unsafe fn size_ptr(&self) -> impl Deref<Target = NonNull<u32>> {
37 DerefWrapper(self.size)
38 }
39
40 #[inline(always)]
41 unsafe fn size_mut_ptr(&mut self) -> impl DerefMut<Target = *mut u32> {
42 DerefWrapper(self.size.as_ptr())
43 }
44
45 #[inline(always)]
46 fn capacity(&self) -> u32 {
47 Data::SIZE
48 }
49
50 #[inline(always)]
51 unsafe fn capacity_ptr(&self) -> impl Deref<Target = NonNull<u32>> {
52 DerefWrapper(NonNull::from_ref(&Data::SIZE))
53 }
54
55 #[inline(always)]
56 #[track_caller]
57 unsafe fn set_size(&mut self, size: u32) {
58 debug_assert!(
59 size == 0 || size == self.size(),
60 "`set_size` called with invalid input {size} (self size {})",
61 self.size()
62 );
63
64 unsafe {
66 self.size.write(size);
67 }
68 }
69
70 #[inline(always)]
71 #[track_caller]
72 unsafe fn from_ptr<'a>(
73 data: &'a NonNull<Self::PointerType>,
74 size: &'a u32,
75 capacity: u32,
76 ) -> impl Deref<Target = Self> + 'a {
77 debug_assert!(data.is_aligned(), "Misaligned pointer");
78 debug_assert!(
79 *size == 0 || *size <= capacity,
80 "Invalid size {size} for capacity {capacity}"
81 );
82 debug_assert!(
84 capacity == 0 || capacity >= Data::SIZE,
85 "Invalid capacity {capacity} for size {}",
86 Data::SIZE
87 );
88
89 let size = NonNull::from_ref(size);
90
91 DerefWrapper(MaybeData { data: *data, size })
92 }
93
94 #[inline(always)]
95 #[track_caller]
96 unsafe fn from_mut_ptr<'a>(
97 data: &'a mut NonNull<Self::PointerType>,
98 size: &'a mut *mut u32,
99 capacity: u32,
100 ) -> impl DerefMut<Target = Self> + 'a {
101 debug_assert!(!size.is_null(), "`null` pointer for non-`TrivialType` size");
102 let size = unsafe { NonNull::new_unchecked(*size) };
104 debug_assert!(data.is_aligned(), "Misaligned pointer");
105 {
107 let size = unsafe { size.read() };
108 debug_assert!(
109 size == 0 || size <= capacity,
110 "Invalid size {size} for capacity {capacity}"
111 );
112 }
113 debug_assert!(
114 capacity >= Data::SIZE,
115 "Invalid capacity {capacity} for size {}",
116 Data::SIZE
117 );
118
119 DerefWrapper(MaybeData { data: *data, size })
120 }
121
122 #[inline(always)]
123 unsafe fn as_ptr(&self) -> impl Deref<Target = NonNull<Self::PointerType>> {
124 &self.data
125 }
126
127 #[inline(always)]
128 unsafe fn as_mut_ptr(&mut self) -> impl DerefMut<Target = NonNull<Self::PointerType>> {
129 &mut self.data
130 }
131}
132
133impl<Data> IoTypeOptional for MaybeData<Data> where Data: TrivialType {}
134
135impl<Data> MaybeData<Data>
136where
137 Data: TrivialType,
138{
139 pub const fn from_buffer(data: Option<&'_ Data>) -> impl Deref<Target = Self> + '_ {
144 let (data, size) = if let Some(data) = data {
145 (NonNull::from_ref(data), &Data::SIZE)
146 } else {
147 (NonNull::dangling(), &0)
148 };
149
150 DerefWrapper(Self {
151 data,
152 size: NonNull::from_ref(size),
153 })
154 }
155
156 #[track_caller]
167 pub fn from_buffer_mut<'a>(
168 buffer: &'a mut Data,
169 size: &'a mut u32,
170 ) -> impl DerefMut<Target = Self> + 'a {
171 debug_assert!(
172 *size == 0 || *size == Data::SIZE,
173 "Invalid size {size} (self size {})",
174 Data::SIZE
175 );
176
177 DerefWrapper(Self {
178 data: NonNull::from_mut(buffer),
179 size: NonNull::from_ref(size),
180 })
181 }
182
183 #[track_caller]
195 pub fn from_uninit<'a>(
196 uninit: &'a mut MaybeUninit<Data>,
197 size: &'a mut u32,
198 ) -> impl DerefMut<Target = Self> + 'a {
199 debug_assert_eq!(*size, 0, "Invalid size");
200
201 DerefWrapper(Self {
202 data: NonNull::from_mut(uninit).cast::<Data>(),
203 size: NonNull::from_mut(size),
204 })
205 }
206
207 #[inline(always)]
209 pub const fn get(&self) -> Option<&Data> {
210 if unsafe { self.size.read() } == Data::SIZE {
212 Some(unsafe { self.data.as_ref() })
214 } else {
215 None
216 }
217 }
218
219 #[inline(always)]
221 pub fn get_mut(&mut self) -> Option<&mut Data> {
222 if unsafe { self.size.read() } == Data::SIZE {
224 Some(unsafe { self.data.as_mut() })
226 } else {
227 None
228 }
229 }
230
231 #[inline(always)]
233 pub fn replace(&mut self, data: Data) -> &mut Data {
234 unsafe {
236 self.size.write(Data::SIZE);
237 }
238 unsafe {
240 self.data.write(data);
241 self.data.as_mut()
242 }
243 }
244
245 #[inline(always)]
247 pub fn remove(&mut self) {
248 unsafe {
250 self.size.write(0);
251 }
252 }
253
254 #[inline(always)]
257 pub fn get_mut_or_init_with<Init>(&mut self, init: Init) -> &mut Data
258 where
259 Init: FnOnce(&mut MaybeUninit<Data>) -> &mut Data,
260 {
261 if unsafe { self.size.read() } == Data::SIZE {
263 unsafe { self.data.as_mut() }
265 } else {
266 let data = init(unsafe { self.data.as_uninit_mut() });
268 unsafe {
270 self.size.write(Data::SIZE);
271 }
272 data
273 }
274 }
275
276 #[inline(always)]
281 pub unsafe fn assume_init(&mut self) -> &mut Data {
282 unsafe {
284 self.size.write(Data::SIZE);
285 }
286 unsafe { self.data.as_mut() }
289 }
290}
291
292impl<Data> MaybeData<Data>
293where
294 Data: TrivialType + Default,
295{
296 #[inline(always)]
298 pub fn get_mut_or_default(&mut self) -> &mut Data {
299 self.get_mut_or_init_with(|data| data.write(Data::default()))
300 }
301}