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 capacity: u32,
20}
21
22unsafe 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 self.size()
49 }
50
51 #[inline(always)]
52 unsafe fn capacity_ptr(&self) -> impl Deref<Target = NonNull<u32>> {
53 DerefWrapper(NonNull::from_ref(&self.capacity))
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!(
84 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 {
92 data: *data,
93 size,
94 capacity,
95 })
96 }
97
98 #[inline(always)]
99 #[track_caller]
100 unsafe fn from_mut_ptr<'a>(
101 data: &'a mut NonNull<Self::PointerType>,
102 size: &'a mut *mut u32,
103 capacity: u32,
104 ) -> impl DerefMut<Target = Self> + 'a {
105 debug_assert!(!size.is_null(), "`null` pointer for non-`TrivialType` size");
106 let size = unsafe { NonNull::new_unchecked(*size) };
108 debug_assert!(data.is_aligned(), "Misaligned pointer");
109 {
111 let size = unsafe { size.read() };
112 debug_assert!(
113 size == 0 || size == capacity,
114 "Invalid size {size} for capacity {capacity}"
115 );
116 }
117 debug_assert!(
118 capacity >= Data::SIZE,
119 "Invalid capacity {capacity} for size {}",
120 Data::SIZE
121 );
122
123 DerefWrapper(MaybeData {
124 data: *data,
125 size,
126 capacity,
127 })
128 }
129
130 #[inline(always)]
131 unsafe fn as_ptr(&self) -> impl Deref<Target = NonNull<Self::PointerType>> {
132 &self.data
133 }
134
135 #[inline(always)]
136 unsafe fn as_mut_ptr(&mut self) -> impl DerefMut<Target = NonNull<Self::PointerType>> {
137 &mut self.data
138 }
139}
140
141impl<Data> IoTypeOptional for MaybeData<Data> where Data: TrivialType {}
142
143impl<Data> MaybeData<Data>
144where
145 Data: TrivialType,
146{
147 pub const fn from_buffer(data: Option<&'_ Data>) -> impl Deref<Target = Self> + '_ {
152 let (data, size) = if let Some(data) = data {
153 (NonNull::from_ref(data), &Data::SIZE)
154 } else {
155 (NonNull::dangling(), &0)
156 };
157
158 DerefWrapper(Self {
159 data,
160 size: NonNull::from_ref(size),
161 capacity: Data::SIZE,
162 })
163 }
164
165 #[track_caller]
176 pub fn from_buffer_mut<'a>(
177 buffer: &'a mut Data,
178 size: &'a mut u32,
179 ) -> impl DerefMut<Target = Self> + 'a {
180 debug_assert!(
181 *size == 0 || *size == Data::SIZE,
182 "Invalid size {size} (self size {})",
183 Data::SIZE
184 );
185
186 DerefWrapper(Self {
187 data: NonNull::from_mut(buffer),
188 size: NonNull::from_ref(size),
189 capacity: Data::SIZE,
190 })
191 }
192
193 #[track_caller]
205 pub fn from_uninit<'a>(
206 uninit: &'a mut MaybeUninit<Data>,
207 size: &'a mut u32,
208 ) -> impl DerefMut<Target = Self> + 'a {
209 debug_assert_eq!(*size, 0, "Invalid size");
210
211 DerefWrapper(Self {
212 data: NonNull::from_mut(uninit).cast::<Data>(),
213 size: NonNull::from_mut(size),
214 capacity: Data::SIZE,
215 })
216 }
217
218 #[inline(always)]
220 pub const fn get(&self) -> Option<&Data> {
221 if unsafe { self.size.read() } == self.capacity {
223 Some(unsafe { self.data.as_ref() })
225 } else {
226 None
227 }
228 }
229
230 #[inline(always)]
232 pub fn get_mut(&mut self) -> Option<&mut Data> {
233 if unsafe { self.size.read() } == self.capacity {
235 Some(unsafe { self.data.as_mut() })
237 } else {
238 None
239 }
240 }
241
242 #[inline(always)]
244 pub fn replace(&mut self, data: Data) -> &mut Data {
245 unsafe {
247 self.size.write(self.capacity);
248 }
249 unsafe {
251 self.data.write(data);
252 self.data.as_mut()
253 }
254 }
255
256 #[inline(always)]
258 pub fn remove(&mut self) {
259 unsafe {
261 self.size.write(0);
262 }
263 }
264
265 #[inline(always)]
268 pub fn get_mut_or_init_with<'a, Init>(&'a mut self, init: Init) -> &'a mut Data
269 where
270 Init: FnOnce(NonNull<Data>) -> &'a mut Data,
271 {
272 if unsafe { self.size.read() } == self.capacity {
274 unsafe { self.data.as_mut() }
276 } else {
277 let data = init(self.data);
278 unsafe {
280 self.size.write(self.capacity);
281 }
282 data
283 }
284 }
285
286 #[inline(always)]
291 pub unsafe fn assume_init(&mut self) -> &mut Data {
292 unsafe {
294 self.size.write(self.capacity);
295 }
296 unsafe { self.data.as_mut() }
299 }
300}