osom_lib_arrays/fixed_array/
fixed_array.rs1use core::{
4 borrow::{Borrow, BorrowMut},
5 hash::Hash,
6};
7
8use osom_lib_alloc::traits::Allocator;
9use osom_lib_primitives::length::Length;
10use osom_lib_reprc::traits::ReprC;
11use osom_lib_try_clone::TryClone;
12
13use crate::{
14 dynamic_array::internal_array::InternalArray,
15 errors::{ArrayError, ArrayIsEmptyError, ArrayTryCloneError},
16 traits::{ImmutableArray, MutableArray},
17};
18
19#[derive(Debug)]
25#[repr(transparent)]
26#[must_use]
27pub struct FixedArray<T, TAllocator>
28where
29 TAllocator: Allocator,
30{
31 inner: InternalArray<T, TAllocator>,
32}
33
34unsafe impl<T, TAllocator> Send for FixedArray<T, TAllocator>
35where
36 T: Sized + Send,
37 TAllocator: Allocator + Send,
38{
39}
40
41unsafe impl<T, TAllocator> Sync for FixedArray<T, TAllocator>
42where
43 T: Sized + Sync,
44 TAllocator: Allocator + Sync,
45{
46}
47
48unsafe impl<T, TAllocator> ReprC for FixedArray<T, TAllocator>
49where
50 T: ReprC,
51 TAllocator: Allocator,
52{
53 const CHECK: () = const {
54 osom_lib_reprc::hidden::is_reprc::<InternalArray<T, TAllocator>>();
55 };
56}
57
58impl<T, TAllocator> FixedArray<T, TAllocator>
59where
60 TAllocator: Allocator,
61{
62 #[inline(always)]
69 pub fn with_capacity_and_allocator(capacity: Length, allocator: TAllocator) -> Result<Self, ArrayError> {
70 let inner = InternalArray::<T, TAllocator>::with_capacity(capacity, allocator)?;
71 Ok(Self { inner })
72 }
73
74 #[inline(always)]
81 pub fn with_capacity(capacity: Length) -> Result<Self, ArrayError>
82 where
83 TAllocator: Default,
84 {
85 Self::with_capacity_and_allocator(capacity, TAllocator::default())
86 }
87
88 #[inline(always)]
95 pub fn with_factory<Factory: FnMut(usize) -> T>(size: Length, factory: Factory) -> Result<Self, ArrayError>
96 where
97 TAllocator: Default,
98 {
99 Self::with_factory_and_allocator(size, factory, TAllocator::default())
100 }
101
102 pub fn with_factory_and_allocator<Factory: FnMut(usize) -> T>(
109 size: Length,
110 mut factory: Factory,
111 allocator: TAllocator,
112 ) -> Result<Self, ArrayError> {
113 unsafe {
114 let mut array = Self::with_size_and_allocator_uninitialized(size, allocator)?;
115 let slice_mut_ptr = array.as_mut().as_mut_ptr();
116 for idx in 0..size.as_usize() {
117 slice_mut_ptr.add(idx).write(factory(idx));
118 }
119 Ok(array)
120 }
121 }
122
123 #[inline(always)]
134 pub unsafe fn with_size_uninitialized(size: Length) -> Result<Self, ArrayError>
135 where
136 TAllocator: Default,
137 {
138 unsafe { Self::with_size_and_allocator_uninitialized(size, TAllocator::default()) }
139 }
140
141 pub unsafe fn with_size_and_allocator_uninitialized(
152 size: Length,
153 allocator: TAllocator,
154 ) -> Result<Self, ArrayError> {
155 let inner = unsafe { InternalArray::with_size_uninitialized(size, allocator) }?;
156 Ok(Self { inner })
157 }
158}
159
160impl<T, TAllocator> ImmutableArray<T> for FixedArray<T, TAllocator>
161where
162 TAllocator: Allocator,
163{
164 #[inline(always)]
165 fn length(&self) -> Length {
166 self.inner.length()
167 }
168
169 #[inline(always)]
170 fn capacity(&self) -> Length {
171 self.inner.capacity()
172 }
173
174 #[inline(always)]
175 fn is_empty(&self) -> bool {
176 self.length().as_u32() == 0
177 }
178}
179
180impl<T, TAllocator> MutableArray<T> for FixedArray<T, TAllocator>
181where
182 TAllocator: Allocator,
183{
184 #[inline(always)]
185 fn try_push_array<const TSIZE: usize>(&mut self, arr: [T; TSIZE]) -> Result<(), ArrayError> {
186 if TSIZE > u32::MAX as usize {
187 return Err(ArrayError::LengthLimitExceeded);
188 }
189 if unsafe { self.inner.length().as_usize().unchecked_add(TSIZE) } > self.inner.capacity().as_usize() {
190 return Err(ArrayError::LengthLimitExceeded);
191 }
192 self.inner.try_push_array(arr)
193 }
194
195 #[inline(always)]
196 fn try_push_slice(&mut self, slice: &[T]) -> Result<(), ArrayTryCloneError>
197 where
198 T: TryClone,
199 {
200 let len = slice.len();
201 if len > u32::MAX as usize {
202 return Err(ArrayError::LengthLimitExceeded.into());
203 }
204
205 if unsafe { self.inner.length().as_usize().unchecked_add(len) } > self.inner.capacity().as_usize() {
206 return Err(ArrayError::LengthLimitExceeded.into());
207 }
208 self.inner.try_push_slice(slice)
209 }
210
211 #[inline(always)]
212 fn try_pop(&mut self) -> Result<T, ArrayIsEmptyError> {
213 self.inner.try_pop()
214 }
215}
216
217impl<T, TAllocator> Drop for FixedArray<T, TAllocator>
218where
219 TAllocator: Allocator,
220{
221 fn drop(&mut self) {
222 unsafe { self.inner.deallocate() };
223 }
224}
225
226impl<T, TAllocator> Clone for FixedArray<T, TAllocator>
227where
228 T: TryClone,
229 TAllocator: Allocator + TryClone,
230{
231 fn clone(&self) -> Self {
232 self.try_clone().expect("Failed to clone fixed array")
233 }
234}
235
236impl<T, TAllocator> TryClone for FixedArray<T, TAllocator>
237where
238 T: TryClone,
239 TAllocator: Allocator + TryClone,
240{
241 type Error = ArrayTryCloneError;
242
243 fn try_clone(&self) -> Result<Self, Self::Error> {
244 Ok(Self {
245 inner: self.inner.try_clone_perfect()?,
246 })
247 }
248}
249
250impl<T, TAllocator, Rhs> PartialEq<Rhs> for FixedArray<T, TAllocator>
251where
252 T: PartialEq,
253 TAllocator: Allocator,
254 Rhs: AsRef<[T]>,
255{
256 fn eq(&self, other: &Rhs) -> bool {
257 self.as_ref() == other.as_ref()
258 }
259}
260
261impl<T, TAllocator> Eq for FixedArray<T, TAllocator>
262where
263 T: Eq,
264 TAllocator: Allocator,
265{
266}
267
268impl<T, TAllocator> Hash for FixedArray<T, TAllocator>
269where
270 T: Hash,
271 TAllocator: Allocator,
272{
273 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
274 self.as_ref().hash(state);
275 }
276}
277
278impl<T, TAllocator> AsRef<[T]> for FixedArray<T, TAllocator>
279where
280 TAllocator: Allocator,
281{
282 fn as_ref(&self) -> &[T] {
283 self.inner.as_slice()
284 }
285}
286
287impl<T, TAllocator> AsMut<[T]> for FixedArray<T, TAllocator>
288where
289 TAllocator: Allocator,
290{
291 fn as_mut(&mut self) -> &mut [T] {
292 self.inner.as_slice_mut()
293 }
294}
295
296impl<T, TAllocator> Borrow<[T]> for FixedArray<T, TAllocator>
297where
298 TAllocator: Allocator,
299{
300 fn borrow(&self) -> &[T] {
301 self.as_ref()
302 }
303}
304
305impl<T, TAllocator> BorrowMut<[T]> for FixedArray<T, TAllocator>
306where
307 TAllocator: Allocator,
308{
309 fn borrow_mut(&mut self) -> &mut [T] {
310 self.as_mut()
311 }
312}