Skip to main content

osom_lib_arrays/
dynamic_array.rs

1//! Holds the definition of [`DynamicArray`].
2
3use 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;
11
12use crate::{
13    errors::{ArrayError, ArrayIsEmptyError},
14    internal_array::InternalArray,
15    traits::{ImmutableArray, MutableArray},
16};
17
18/// A `#[repr(C)]` variant of the standard `vec` struct.
19///
20/// Functionally similar, and implements [`ReprC`] for `T: ReprC`.
21#[derive(Debug)]
22#[repr(transparent)]
23#[must_use]
24pub struct DynamicArray<T, TAllocator>
25where
26    TAllocator: Allocator,
27{
28    inner: InternalArray<T, TAllocator>,
29}
30
31unsafe impl<T, TAllocator> ReprC for DynamicArray<T, TAllocator>
32where
33    T: ReprC,
34    TAllocator: Allocator,
35{
36    const CHECK: () = {
37        let () = <InternalArray<T, TAllocator> as ReprC>::CHECK;
38    };
39}
40
41impl<T, TAllocator> DynamicArray<T, TAllocator>
42where
43    TAllocator: Allocator,
44{
45    /// Creates a new, empty [`DynamicArray`].
46    #[inline(always)]
47    pub fn new() -> Self {
48        Self::with_allocator(TAllocator::default())
49    }
50
51    /// Creates a new, empty [`DynamicArray`] with an allocator.
52    #[inline(always)]
53    pub const fn with_allocator(allocator: TAllocator) -> Self {
54        Self {
55            inner: InternalArray::new(allocator),
56        }
57    }
58
59    /// Creates a new [`DynamicArray`] with capacity and allocator.
60    /// This allocates memory only when `capacity > 0`.
61    ///
62    /// # Errors
63    ///
64    /// For details see [`ArrayError`].
65    #[inline(always)]
66    pub fn with_capacity_and_allocator(capacity: Length, allocator: TAllocator) -> Result<Self, ArrayError> {
67        let inner = InternalArray::<T, TAllocator>::with_capacity(capacity, allocator)?;
68        Ok(Self { inner })
69    }
70
71    /// Creates a new [`DynamicArray`] with capacity and the default allocator.
72    /// This allocates memory only when `capacity > 0`.
73    ///
74    /// # Errors
75    ///
76    /// For details see [`ArrayError`].
77    #[inline(always)]
78    pub fn with_capacity(capacity: Length) -> Result<Self, ArrayError> {
79        Self::with_capacity_and_allocator(capacity, TAllocator::default())
80    }
81}
82
83impl<T, TAllocator> ImmutableArray<T> for DynamicArray<T, TAllocator>
84where
85    TAllocator: Allocator,
86{
87    #[inline(always)]
88    fn length(&self) -> Length {
89        self.inner.length()
90    }
91
92    #[inline(always)]
93    fn capacity(&self) -> Length {
94        self.inner.capacity()
95    }
96
97    #[inline(always)]
98    fn as_slice(&self) -> &[T] {
99        self.inner.as_slice()
100    }
101
102    #[inline(always)]
103    fn is_empty(&self) -> bool {
104        self.length().as_u32() == 0
105    }
106}
107
108impl<T, TAllocator> MutableArray<T> for DynamicArray<T, TAllocator>
109where
110    TAllocator: Allocator,
111{
112    #[inline(always)]
113    fn try_push_array<const TSIZE: usize>(&mut self, arr: [T; TSIZE]) -> Result<(), ArrayError> {
114        self.inner.try_push_array(arr)
115    }
116
117    #[inline(always)]
118    fn try_push_slice(&mut self, slice: &[T]) -> Result<(), ArrayError>
119    where
120        T: Clone,
121    {
122        self.inner.try_push_slice(slice)
123    }
124
125    #[inline(always)]
126    fn try_pop(&mut self) -> Result<T, ArrayIsEmptyError> {
127        self.inner.try_pop()
128    }
129
130    #[inline(always)]
131    fn as_slice_mut(&mut self) -> &mut [T] {
132        self.inner.as_slice_mut()
133    }
134}
135
136impl<T, TAllocator> Drop for DynamicArray<T, TAllocator>
137where
138    TAllocator: Allocator,
139{
140    fn drop(&mut self) {
141        unsafe { self.inner.deallocate() };
142    }
143}
144
145impl<T, TAllocator> Default for DynamicArray<T, TAllocator>
146where
147    TAllocator: Allocator,
148{
149    fn default() -> Self {
150        Self::new()
151    }
152}
153
154impl<T: Clone, TAllocator> Clone for DynamicArray<T, TAllocator>
155where
156    TAllocator: Allocator,
157{
158    fn clone(&self) -> Self {
159        Self {
160            inner: self.inner.clone(),
161        }
162    }
163}
164
165impl<T, TAllocator, Rhs> PartialEq<Rhs> for DynamicArray<T, TAllocator>
166where
167    T: PartialEq,
168    TAllocator: Allocator,
169    Rhs: AsRef<[T]>,
170{
171    fn eq(&self, other: &Rhs) -> bool {
172        self.as_slice() == other.as_ref()
173    }
174}
175
176impl<T, TAllocator> Eq for DynamicArray<T, TAllocator>
177where
178    T: Eq,
179    TAllocator: Allocator,
180{
181}
182
183impl<T, TAllocator> Hash for DynamicArray<T, TAllocator>
184where
185    T: Hash,
186    TAllocator: Allocator,
187{
188    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
189        self.as_slice().hash(state);
190    }
191}
192
193impl<T, TAllocator> AsRef<[T]> for DynamicArray<T, TAllocator>
194where
195    TAllocator: Allocator,
196{
197    fn as_ref(&self) -> &[T] {
198        self.as_slice()
199    }
200}
201
202impl<T, TAllocator> AsMut<[T]> for DynamicArray<T, TAllocator>
203where
204    TAllocator: Allocator,
205{
206    fn as_mut(&mut self) -> &mut [T] {
207        self.as_slice_mut()
208    }
209}
210
211impl<T, TAllocator> Borrow<[T]> for DynamicArray<T, TAllocator>
212where
213    TAllocator: Allocator,
214{
215    fn borrow(&self) -> &[T] {
216        self.as_slice()
217    }
218}
219
220impl<T, TAllocator> BorrowMut<[T]> for DynamicArray<T, TAllocator>
221where
222    TAllocator: Allocator,
223{
224    fn borrow_mut(&mut self) -> &mut [T] {
225        self.as_slice_mut()
226    }
227}
228
229impl<T, TAllocator> core::ops::Index<Length> for DynamicArray<T, TAllocator>
230where
231    TAllocator: Allocator,
232{
233    type Output = T;
234
235    #[inline(always)]
236    fn index(&self, index: Length) -> &Self::Output {
237        &self.as_slice()[index.as_usize()]
238    }
239}
240
241impl<T, TAllocator> core::ops::IndexMut<Length> for DynamicArray<T, TAllocator>
242where
243    TAllocator: Allocator,
244{
245    #[inline(always)]
246    fn index_mut(&mut self, index: Length) -> &mut Self::Output {
247        &mut self.as_slice_mut()[index.as_usize()]
248    }
249}