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;
69
70 #[inline(always)]
71 fn size(&self) -> u32 {
72 self.size()
73 }
74
75 #[inline(always)]
76 fn capacity(&self) -> u32 {
77 self.capacity
78 }
79
80 #[inline(always)]
81 #[track_caller]
82 unsafe fn set_size(&mut self, size: u32) {
83 debug_assert!(
84 size <= self.capacity,
85 "`set_size` called with invalid input {size} for capacity {}",
86 self.capacity
87 );
88 debug_assert!(
89 size.is_multiple_of(Element::SIZE),
90 "`set_size` called with invalid input {size} for element size {}",
91 Element::SIZE
92 );
93
94 unsafe {
96 self.size.write(size);
97 }
98 }
99
100 #[inline(always)]
101 #[track_caller]
102 unsafe fn from_ptr<'a>(
103 ptr: &'a NonNull<Self::PointerType>,
104 size: &'a u32,
105 capacity: u32,
106 ) -> impl Deref<Target = Self> + 'a {
107 debug_assert!(ptr.is_aligned(), "Misaligned pointer");
108 debug_assert!(
109 *size <= capacity,
110 "Size {size} must not exceed capacity {capacity}"
111 );
112 debug_assert!(
113 size.is_multiple_of(Element::SIZE),
114 "Size {size} is invalid for element size {}",
115 Element::SIZE
116 );
117
118 DerefWrapper(Self {
119 elements: *ptr,
120 size: NonNull::from_ref(size),
121 capacity,
122 })
123 }
124
125 #[inline(always)]
126 #[track_caller]
127 unsafe fn from_mut_ptr<'a>(
128 ptr: &'a mut NonNull<Self::PointerType>,
129 size: &'a mut u32,
130 capacity: u32,
131 ) -> impl DerefMut<Target = Self> + 'a {
132 debug_assert!(ptr.is_aligned(), "Misaligned pointer");
133 debug_assert!(
134 *size <= capacity,
135 "Size {size} must not exceed capacity {capacity}"
136 );
137 debug_assert!(
138 size.is_multiple_of(Element::SIZE),
139 "Size {size} is invalid for element size {}",
140 Element::SIZE
141 );
142
143 DerefWrapper(Self {
144 elements: *ptr,
145 size: NonNull::from_mut(size),
146 capacity,
147 })
148 }
149
150 #[inline(always)]
151 unsafe fn as_ptr(&self) -> impl Deref<Target = NonNull<Self::PointerType>> {
152 &self.elements
153 }
154
155 #[inline(always)]
156 unsafe fn as_mut_ptr(&mut self) -> impl DerefMut<Target = NonNull<Self::PointerType>> {
157 &mut self.elements
158 }
159}
160
161impl<Element, const RECOMMENDED_ALLOCATION: u32> IoTypeOptional
162 for VariableElements<Element, RECOMMENDED_ALLOCATION>
163where
164 Element: TrivialType,
165{
166}
167
168impl<Element, const RECOMMENDED_ALLOCATION: u32> VariableElements<Element, RECOMMENDED_ALLOCATION>
169where
170 Element: TrivialType,
171{
172 #[inline(always)]
182 #[track_caller]
183 pub const fn from_buffer<'a>(
184 buffer: &'a [<Self as IoType>::PointerType],
185 size: &'a u32,
186 ) -> impl Deref<Target = Self> + 'a {
187 debug_assert!(
188 buffer.len() * Element::SIZE as usize == *size as usize,
189 "Invalid size"
190 );
191 DerefWrapper(Self {
195 elements: NonNull::new(buffer.as_ptr().cast_mut()).expect("Not null; qed"),
196 size: NonNull::from_ref(size),
197 capacity: *size,
198 })
199 }
200
201 #[inline(always)]
209 #[track_caller]
210 pub fn from_buffer_mut<'a>(
211 buffer: &'a mut [<Self as IoType>::PointerType],
212 size: &'a mut u32,
213 ) -> impl DerefMut<Target = Self> + 'a {
214 debug_assert_eq!(
215 buffer.len() * Element::SIZE as usize,
216 *size as usize,
217 "Invalid size"
218 );
219
220 DerefWrapper(Self {
221 elements: NonNull::new(buffer.as_mut_ptr()).expect("Not null; qed"),
222 size: NonNull::from_mut(size),
223 capacity: *size,
224 })
225 }
226
227 #[inline(always)]
237 #[track_caller]
238 pub fn from_uninit<'a>(
239 uninit: &'a mut [MaybeUninit<<Self as IoType>::PointerType>],
240 size: &'a mut u32,
241 ) -> impl DerefMut<Target = Self> + 'a {
242 let capacity = uninit.len();
243 debug_assert!(
244 *size as usize <= capacity,
245 "Size {size} must not exceed capacity {capacity}"
246 );
247 debug_assert!(
248 size.is_multiple_of(Element::SIZE),
249 "Size {size} is invalid for element size {}",
250 Element::SIZE
251 );
252 let capacity = capacity as u32;
253
254 DerefWrapper(Self {
255 elements: NonNull::new(uninit.as_mut_ptr().cast_init()).expect("Not null; qed"),
256 size: NonNull::from_mut(size),
257 capacity,
258 })
259 }
260
261 #[inline(always)]
263 pub const fn size(&self) -> u32 {
264 unsafe { self.size.read() }
266 }
267
268 #[inline(always)]
270 pub fn capacity(&self) -> u32 {
271 self.capacity
272 }
273
274 #[inline(always)]
276 pub const fn count(&self) -> u32 {
277 unsafe { self.size.read() }
279 }
280
281 #[inline(always)]
283 pub const fn get_initialized(&self) -> &[Element] {
284 let size = self.size();
285 let ptr = self.elements.as_ptr();
286 unsafe { slice::from_raw_parts(ptr, (size / Element::SIZE) as usize) }
288 }
289
290 #[inline(always)]
292 pub fn get_initialized_mut(&mut self) -> &mut [Element] {
293 let size = self.size();
294 let ptr = self.elements.as_ptr();
295 unsafe { slice::from_raw_parts_mut(ptr, (size / Element::SIZE) as usize) }
297 }
298
299 #[inline(always)]
303 #[must_use = "Operation may fail"]
304 pub fn append(&mut self, elements: &[Element]) -> bool {
305 let size = self.size();
306 if elements.len() * Element::SIZE as usize + size as usize > self.capacity as usize {
307 return false;
308 }
309
310 let Ok(offset) = isize::try_from(size / Element::SIZE) else {
312 return false;
313 };
314
315 let mut start = unsafe { self.elements.offset(offset) };
318 unsafe { ptr::copy_nonoverlapping(elements.as_ptr(), start.as_mut(), elements.len()) }
323
324 true
325 }
326
327 #[inline(always)]
332 #[must_use = "Operation may fail"]
333 pub fn truncate(&mut self, new_size: u32) -> bool {
334 if new_size > self.size() || !new_size.is_multiple_of(Element::SIZE) {
335 return false;
336 }
337
338 unsafe {
340 self.size.write(new_size);
341 }
342
343 true
344 }
345
346 #[inline(always)]
350 #[must_use = "Operation may fail"]
351 pub fn copy_from(&mut self, src: &Self) -> bool {
352 let src_size = src.size();
353 if src_size > self.capacity {
354 return false;
355 }
356
357 unsafe {
360 self.elements
361 .copy_from_nonoverlapping(src.elements, src_size as usize);
362 self.size.write(src_size);
363 }
364
365 true
366 }
367
368 #[inline(always)]
373 pub fn as_mut_ptr(&mut self) -> &mut NonNull<Element> {
374 &mut self.elements
375 }
376
377 #[inline(always)]
380 pub fn cast_ref<const DIFFERENT_RECOMMENDED_ALLOCATION: u32>(
381 &self,
382 ) -> &VariableElements<Element, DIFFERENT_RECOMMENDED_ALLOCATION> {
383 unsafe {
386 NonNull::from_ref(self)
387 .cast::<VariableElements<Element, DIFFERENT_RECOMMENDED_ALLOCATION>>()
388 .as_ref()
389 }
390 }
391
392 #[inline(always)]
395 pub fn cast_mut<const DIFFERENT_RECOMMENDED_ALLOCATION: u32>(
396 &mut self,
397 ) -> &mut VariableElements<Element, DIFFERENT_RECOMMENDED_ALLOCATION> {
398 unsafe {
401 NonNull::from_mut(self)
402 .cast::<VariableElements<Element, DIFFERENT_RECOMMENDED_ALLOCATION>>()
403 .as_mut()
404 }
405 }
406
407 #[inline(always)]
415 #[must_use = "Operation may fail"]
416 pub unsafe fn assume_init(&mut self, size: u32) -> Option<&mut [Element]> {
417 if size > self.capacity || !size.is_multiple_of(Element::SIZE) {
418 return None;
419 }
420
421 unsafe {
423 self.size.write(size);
424 }
425 Some(self.get_initialized_mut())
426 }
427}