1use crate::metadata::{IoTypeMetadataKind, MAX_METADATA_CAPACITY, concat_metadata_sources};
2use crate::trivial_type::TrivialType;
3use crate::{DerefWrapper, IoType, IoTypeOptional};
4use core::mem::MaybeUninit;
5use core::ops::{Deref, DerefMut};
6use core::ptr::NonNull;
7use core::{ptr, slice};
8
9#[derive(Debug)]
16#[repr(C)]
17pub struct VariableElements<Element, const RECOMMENDED_ALLOCATION: u32 = 0>
18where
19 Element: TrivialType,
20{
21 elements: NonNull<Element>,
22 size: NonNull<u32>,
23 capacity: u32,
24}
25
26unsafe impl<Element, const RECOMMENDED_ALLOCATION: u32> IoType
28 for VariableElements<Element, RECOMMENDED_ALLOCATION>
29where
30 Element: TrivialType,
31{
32 const METADATA: &[u8] = {
33 const fn metadata(
34 recommended_allocation: u32,
35 inner_metadata: &[u8],
36 ) -> ([u8; MAX_METADATA_CAPACITY], usize) {
37 if recommended_allocation == 0 {
38 return concat_metadata_sources(&[
39 &[IoTypeMetadataKind::VariableElements0 as u8],
40 inner_metadata,
41 ]);
42 }
43
44 let (io_type, size_bytes) = if recommended_allocation < 2u32.pow(8) {
45 (IoTypeMetadataKind::VariableElements8b, 1)
46 } else if recommended_allocation < 2u32.pow(16) {
47 (IoTypeMetadataKind::VariableElements16b, 2)
48 } else {
49 (IoTypeMetadataKind::VariableElements32b, 4)
50 };
51
52 concat_metadata_sources(&[
53 &[io_type as u8],
54 recommended_allocation.to_le_bytes().split_at(size_bytes).0,
55 inner_metadata,
56 ])
57 }
58
59 metadata(RECOMMENDED_ALLOCATION, Element::METADATA)
61 .0
62 .split_at(metadata(RECOMMENDED_ALLOCATION, Element::METADATA).1)
63 .0
64 };
65
66 type PointerType = Element;
68
69 #[inline(always)]
70 fn size(&self) -> u32 {
71 self.size()
72 }
73
74 #[inline(always)]
75 fn capacity(&self) -> u32 {
76 self.capacity
77 }
78
79 #[inline(always)]
80 #[track_caller]
81 unsafe fn set_size(&mut self, size: u32) {
82 debug_assert!(
83 size <= self.capacity,
84 "`set_size` called with invalid input {size} for capacity {}",
85 self.capacity
86 );
87 debug_assert!(
88 size.is_multiple_of(Element::SIZE),
89 "`set_size` called with invalid input {size} for element size {}",
90 Element::SIZE
91 );
92
93 unsafe {
95 self.size.write(size);
96 }
97 }
98
99 #[inline(always)]
100 #[track_caller]
101 unsafe fn from_ptr<'a>(
102 ptr: &'a NonNull<Self::PointerType>,
103 size: &'a u32,
104 capacity: u32,
105 ) -> impl Deref<Target = Self> + 'a {
106 debug_assert!(ptr.is_aligned(), "Misaligned pointer");
107 debug_assert!(
108 *size <= capacity,
109 "Size {size} must not exceed capacity {capacity}"
110 );
111 debug_assert!(
112 size.is_multiple_of(Element::SIZE),
113 "Size {size} is invalid for element size {}",
114 Element::SIZE
115 );
116
117 DerefWrapper(Self {
118 elements: *ptr,
119 size: NonNull::from_ref(size),
120 capacity,
121 })
122 }
123
124 #[inline(always)]
125 #[track_caller]
126 unsafe fn from_mut_ptr<'a>(
127 ptr: &'a mut NonNull<Self::PointerType>,
128 size: &'a mut u32,
129 capacity: u32,
130 ) -> impl DerefMut<Target = Self> + 'a {
131 debug_assert!(ptr.is_aligned(), "Misaligned pointer");
132 debug_assert!(
133 *size <= capacity,
134 "Size {size} must not exceed capacity {capacity}"
135 );
136 debug_assert!(
137 size.is_multiple_of(Element::SIZE),
138 "Size {size} is invalid for element size {}",
139 Element::SIZE
140 );
141
142 DerefWrapper(Self {
143 elements: *ptr,
144 size: NonNull::from_mut(size),
145 capacity,
146 })
147 }
148
149 #[inline(always)]
150 unsafe fn as_ptr(&self) -> impl Deref<Target = NonNull<Self::PointerType>> {
151 &self.elements
152 }
153
154 #[inline(always)]
155 unsafe fn as_mut_ptr(&mut self) -> impl DerefMut<Target = NonNull<Self::PointerType>> {
156 &mut self.elements
157 }
158}
159
160impl<Element, const RECOMMENDED_ALLOCATION: u32> IoTypeOptional
161 for VariableElements<Element, RECOMMENDED_ALLOCATION>
162where
163 Element: TrivialType,
164{
165}
166
167impl<Element, const RECOMMENDED_ALLOCATION: u32> VariableElements<Element, RECOMMENDED_ALLOCATION>
168where
169 Element: TrivialType,
170{
171 #[inline(always)]
181 #[track_caller]
182 pub const fn from_buffer<'a>(
183 buffer: &'a [<Self as IoType>::PointerType],
184 size: &'a u32,
185 ) -> impl Deref<Target = Self> + 'a {
186 debug_assert!(
187 buffer.len() * Element::SIZE as usize == *size as usize,
188 "Invalid size"
189 );
190 DerefWrapper(Self {
194 elements: NonNull::new(buffer.as_ptr().cast_mut()).expect("Not null; qed"),
195 size: NonNull::from_ref(size),
196 capacity: *size,
197 })
198 }
199
200 #[inline(always)]
208 #[track_caller]
209 pub fn from_buffer_mut<'a>(
210 buffer: &'a mut [<Self as IoType>::PointerType],
211 size: &'a mut u32,
212 ) -> impl DerefMut<Target = Self> + 'a {
213 debug_assert_eq!(
214 buffer.len() * Element::SIZE as usize,
215 *size as usize,
216 "Invalid size"
217 );
218
219 DerefWrapper(Self {
220 elements: NonNull::new(buffer.as_mut_ptr()).expect("Not null; qed"),
221 size: NonNull::from_mut(size),
222 capacity: *size,
223 })
224 }
225
226 #[inline(always)]
236 #[track_caller]
237 pub fn from_uninit<'a>(
238 uninit: &'a mut [MaybeUninit<<Self as IoType>::PointerType>],
239 size: &'a mut u32,
240 ) -> impl DerefMut<Target = Self> + 'a {
241 let capacity = uninit.len();
242 debug_assert!(
243 *size as usize <= capacity,
244 "Size {size} must not exceed capacity {capacity}"
245 );
246 debug_assert!(
247 size.is_multiple_of(Element::SIZE),
248 "Size {size} is invalid for element size {}",
249 Element::SIZE
250 );
251 let capacity = capacity as u32;
252
253 DerefWrapper(Self {
254 elements: NonNull::new(uninit.as_mut_ptr().cast_init()).expect("Not null; qed"),
255 size: NonNull::from_mut(size),
256 capacity,
257 })
258 }
259
260 #[inline(always)]
262 pub const fn size(&self) -> u32 {
263 unsafe { self.size.read() }
265 }
266
267 #[inline(always)]
269 pub fn capacity(&self) -> u32 {
270 self.capacity
271 }
272
273 #[inline(always)]
275 pub const fn count(&self) -> u32 {
276 unsafe { self.size.read() }
278 }
279
280 #[inline(always)]
282 pub const fn get_initialized(&self) -> &[Element] {
283 let size = self.size();
284 let ptr = self.elements.as_ptr();
285 unsafe { slice::from_raw_parts(ptr, (size / Element::SIZE) as usize) }
287 }
288
289 #[inline(always)]
291 pub fn get_initialized_mut(&mut self) -> &mut [Element] {
292 let size = self.size();
293 let ptr = self.elements.as_ptr();
294 unsafe { slice::from_raw_parts_mut(ptr, (size / Element::SIZE) as usize) }
296 }
297
298 #[inline(always)]
302 #[must_use = "Operation may fail"]
303 pub fn append(&mut self, elements: &[Element]) -> bool {
304 let size = self.size();
305 if elements.len() * Element::SIZE as usize + size as usize > self.capacity as usize {
306 return false;
307 }
308
309 let Ok(offset) = isize::try_from(size / Element::SIZE) else {
311 return false;
312 };
313
314 let mut start = unsafe { self.elements.offset(offset) };
317 unsafe { ptr::copy_nonoverlapping(elements.as_ptr(), start.as_mut(), elements.len()) }
322
323 true
324 }
325
326 #[inline(always)]
331 #[must_use = "Operation may fail"]
332 pub fn truncate(&mut self, new_size: u32) -> bool {
333 if new_size > self.size() || !new_size.is_multiple_of(Element::SIZE) {
334 return false;
335 }
336
337 unsafe {
339 self.size.write(new_size);
340 }
341
342 true
343 }
344
345 #[inline(always)]
349 #[must_use = "Operation may fail"]
350 pub fn copy_from(&mut self, src: &Self) -> bool {
351 let src_size = src.size();
352 if src_size > self.capacity {
353 return false;
354 }
355
356 unsafe {
359 self.elements
360 .copy_from_nonoverlapping(src.elements, src_size as usize);
361 self.size.write(src_size);
362 }
363
364 true
365 }
366
367 #[inline(always)]
372 pub fn as_mut_ptr(&mut self) -> &mut NonNull<Element> {
373 &mut self.elements
374 }
375
376 #[inline(always)]
379 pub fn cast_ref<const DIFFERENT_RECOMMENDED_ALLOCATION: u32>(
380 &self,
381 ) -> &VariableElements<Element, DIFFERENT_RECOMMENDED_ALLOCATION> {
382 unsafe {
385 NonNull::from_ref(self)
386 .cast::<VariableElements<Element, DIFFERENT_RECOMMENDED_ALLOCATION>>()
387 .as_ref()
388 }
389 }
390
391 #[inline(always)]
394 pub fn cast_mut<const DIFFERENT_RECOMMENDED_ALLOCATION: u32>(
395 &mut self,
396 ) -> &mut VariableElements<Element, DIFFERENT_RECOMMENDED_ALLOCATION> {
397 unsafe {
400 NonNull::from_mut(self)
401 .cast::<VariableElements<Element, DIFFERENT_RECOMMENDED_ALLOCATION>>()
402 .as_mut()
403 }
404 }
405
406 #[inline(always)]
414 #[must_use = "Operation may fail"]
415 pub unsafe fn assume_init(&mut self, size: u32) -> Option<&mut [Element]> {
416 if size > self.capacity || !size.is_multiple_of(Element::SIZE) {
417 return None;
418 }
419
420 unsafe {
422 self.size.write(size);
423 }
424 Some(self.get_initialized_mut())
425 }
426}