1#![allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
2
3use core::{alloc::Layout, marker::PhantomData, ops::Deref};
4
5use osom_lib_alloc::{AllocatedMemory as _, Allocator};
6
7#[cfg(feature = "std_alloc")]
8use osom_lib_alloc::StdAllocator;
9
10use osom_lib_primitives::Length;
11
12use crate::errors::ArrayConstructionError;
13
14#[must_use]
21pub struct Array<
22 T,
23 #[cfg(feature = "std_alloc")] TAllocator = StdAllocator,
24 #[cfg(not(feature = "std_alloc"))] TAllocator,
25> where
26 TAllocator: Allocator,
27{
28 pub(crate) data: TAllocator::TAllocatedMemory,
29 pub(crate) len: Length,
30 pub(crate) allocator: TAllocator,
31 pub(crate) phantom: PhantomData<T>,
32}
33
34impl<T, TAllocator> Array<T, TAllocator>
35where
36 TAllocator: Allocator,
37{
38 pub const MAX_LENGTH: usize = Length::MAX;
39
40 #[inline(always)]
41 const fn layout(len: usize) -> Layout {
42 let byte_size = len * size_of::<T>();
43 let alignment = align_of::<T>();
44 unsafe { Layout::from_size_align_unchecked(byte_size, alignment) }
45 }
46
47 #[inline(always)]
49 pub fn empty() -> Self {
50 Self::empty_with_allocator(TAllocator::default())
51 }
52
53 #[inline(always)]
61 pub fn empty_with_allocator(allocator: TAllocator) -> Self {
62 Self {
63 data: unsafe { allocator.dangling::<T>() },
64 len: Length::ZERO,
65 allocator: allocator,
66 phantom: PhantomData,
67 }
68 }
69
70 pub fn from_array_with_allocator<const N: usize>(
81 data: [T; N],
82 allocator: TAllocator,
83 ) -> Result<Self, ArrayConstructionError> {
84 if N == 0 {
85 return Ok(Self::empty_with_allocator(allocator));
86 }
87
88 if N > Length::MAX {
89 return Err(ArrayConstructionError::ArrayTooLong);
90 }
91
92 let layout = Self::layout(N);
93 let memory = allocator.allocate(layout)?;
94
95 let array = Self {
96 data: memory,
97 len: unsafe { Length::new_unchecked(N as i32) },
98 allocator: allocator,
99 phantom: PhantomData,
100 };
101
102 let slice_ptr = data.as_ptr();
103 unsafe {
104 array.ptr().copy_from_nonoverlapping(slice_ptr, N);
105 }
106
107 core::mem::forget(data);
108
109 Ok(array)
110 }
111
112 pub fn from_array<const N: usize>(data: [T; N]) -> Result<Self, ArrayConstructionError> {
123 Self::from_array_with_allocator(data, TAllocator::default())
124 }
125
126 #[inline(always)]
128 pub const fn len(&self) -> Length {
129 self.len
130 }
131
132 #[inline(always)]
134 pub const fn is_empty(&self) -> bool {
135 self.len.value() == 0
136 }
137
138 #[inline(always)]
140 pub fn as_slice(&self) -> &[T] {
141 unsafe { core::slice::from_raw_parts(self.ptr(), self.len.into()) }
142 }
143
144 #[inline(always)]
146 pub fn as_slice_mut(&mut self) -> &mut [T] {
147 unsafe { core::slice::from_raw_parts_mut(self.ptr(), self.len.into()) }
148 }
149
150 #[inline(always)]
151 fn ptr(&self) -> *mut T {
152 unsafe { self.data.as_ptr() }
153 }
154}
155
156impl<T, TAllocator> Array<T, TAllocator>
157where
158 T: Clone,
159 TAllocator: Allocator,
160{
161 pub fn from_slice_and_allocator(slice: &[T], allocator: TAllocator) -> Result<Self, ArrayConstructionError> {
172 let len = slice.len();
173 if len == 0 {
174 return Ok(Self::empty_with_allocator(allocator));
175 }
176
177 if len > Length::MAX {
178 return Err(ArrayConstructionError::ArrayTooLong);
179 }
180
181 let layout = Self::layout(len);
182 let memory = allocator.allocate(layout)?;
183
184 let array = Self {
185 data: memory,
186 len: unsafe { Length::new_unchecked(len as i32) },
187 allocator: allocator,
188 phantom: PhantomData,
189 };
190
191 unsafe {
192 let mut target = array.ptr();
193 for item in slice {
194 target.write(item.clone());
195 target = target.add(1);
196 }
197 }
198
199 Ok(array)
200 }
201
202 pub fn from_slice(slice: &[T]) -> Result<Self, ArrayConstructionError> {
213 Self::from_slice_and_allocator(slice, TAllocator::default())
214 }
215}
216
217impl<T, TAllocator> Drop for Array<T, TAllocator>
218where
219 TAllocator: Allocator,
220{
221 fn drop(&mut self) {
222 let len: usize = self.len.into();
223 if len == 0 {
224 return;
225 }
226
227 unsafe {
228 if core::mem::needs_drop::<T>() {
229 let mut ptr = self.ptr();
230 let end = ptr.add(len);
231 while ptr < end {
232 core::ptr::drop_in_place(ptr);
233 ptr = ptr.add(1);
234 }
235 }
236
237 let layout = Self::layout(len);
238 let data = core::ptr::read(&self.data);
239 data.deallocate(layout);
240 }
241 }
242}
243
244impl<T, TAllocator> Clone for Array<T, TAllocator>
245where
246 T: Clone,
247 TAllocator: Allocator,
248{
249 fn clone(&self) -> Self {
250 Self::from_slice_and_allocator(self.as_slice(), self.allocator.clone()).unwrap()
251 }
252}
253
254impl<T, TAllocator> Default for Array<T, TAllocator>
255where
256 TAllocator: Allocator,
257{
258 fn default() -> Self {
259 Self::empty()
260 }
261}
262
263impl<T, TAllocator> Deref for Array<T, TAllocator>
264where
265 TAllocator: Allocator,
266{
267 type Target = [T];
268
269 fn deref(&self) -> &Self::Target {
270 self.as_slice()
271 }
272}
273
274impl<T, TAllocator> core::ops::DerefMut for Array<T, TAllocator>
275where
276 TAllocator: Allocator,
277{
278 fn deref_mut(&mut self) -> &mut Self::Target {
279 self.as_slice_mut()
280 }
281}
282
283impl<T, TAllocator> AsRef<[T]> for Array<T, TAllocator>
284where
285 TAllocator: Allocator,
286{
287 fn as_ref(&self) -> &[T] {
288 self.as_slice()
289 }
290}
291
292impl<T, TAllocator> AsMut<[T]> for Array<T, TAllocator>
293where
294 TAllocator: Allocator,
295{
296 fn as_mut(&mut self) -> &mut [T] {
297 self.as_slice_mut()
298 }
299}