osom_arrays/
dynamic_array.rs

1use core::{
2    borrow::{Borrow, BorrowMut},
3    hash::Hash,
4};
5
6use osom_alloc::Allocator;
7use osom_primitives::length::Length;
8
9use crate::{
10    errors::ArrayError,
11    internal_array::InternalArray,
12    traits::{ImmutableArray, MutableArray},
13};
14
15/// A `#[repr(C)]` variant of the standard `vec` struct.
16///
17/// Functionally the same, but with slightly different
18/// functionalities.
19#[derive(Debug)]
20#[repr(transparent)]
21#[must_use]
22pub struct DynamicArray<T, TAllocator: Allocator> {
23    inner: InternalArray<T, TAllocator>,
24}
25
26impl<T, TAllocator: Allocator> DynamicArray<T, TAllocator> {
27    /// Creates a new, empty [`DynamicArray`].
28    #[inline(always)]
29    pub fn new() -> Self {
30        Self::with_allocator(TAllocator::default())
31    }
32
33    /// Creates a new, empty [`DynamicArray`] with an allocator.
34    #[inline(always)]
35    pub const fn with_allocator(allocator: TAllocator) -> Self {
36        Self {
37            inner: InternalArray::new(allocator),
38        }
39    }
40
41    /// Creates a new [`DynamicArray`] with capacity and allocator.
42    /// This allocates memory only when `capacity > 0`.
43    ///
44    /// # Errors
45    ///
46    /// For details see [`ArrayError`].
47    #[inline(always)]
48    pub fn with_capacity_and_allocator(capacity: Length, allocator: TAllocator) -> Result<Self, ArrayError> {
49        let inner = InternalArray::<T, TAllocator>::with_capacity(capacity, allocator)?;
50        Ok(Self { inner })
51    }
52
53    /// Creates a new [`DynamicArray`] with capacity and the default allocator.
54    /// This allocates memory only when `capacity > 0`.
55    ///
56    /// # Errors
57    ///
58    /// For details see [`ArrayError`].
59    #[inline(always)]
60    pub fn with_capacity(capacity: Length) -> Result<Self, ArrayError> {
61        Self::with_capacity_and_allocator(capacity, TAllocator::default())
62    }
63}
64
65impl<T, TAllocator: Allocator> Drop for DynamicArray<T, TAllocator> {
66    fn drop(&mut self) {
67        unsafe { self.inner.deallocate() };
68    }
69}
70
71impl<T, TAllocator: Allocator> Default for DynamicArray<T, TAllocator> {
72    fn default() -> Self {
73        Self::new()
74    }
75}
76
77impl<T: Clone, TAllocator: Allocator> Clone for DynamicArray<T, TAllocator> {
78    fn clone(&self) -> Self {
79        Self {
80            inner: self.inner.clone(),
81        }
82    }
83}
84
85impl<T, TAllocator: Allocator> ImmutableArray<T> for DynamicArray<T, TAllocator> {
86    #[inline(always)]
87    fn length(&self) -> Length {
88        self.inner.length()
89    }
90
91    #[inline(always)]
92    fn capacity(&self) -> Length {
93        self.inner.capacity()
94    }
95
96    #[inline(always)]
97    fn as_slice(&self) -> &[T] {
98        self.inner.as_slice()
99    }
100}
101
102impl<T, TAllocator: Allocator> MutableArray<T> for DynamicArray<T, TAllocator> {
103    #[inline(always)]
104    fn try_push_array<const TSIZE: usize>(&mut self, arr: [T; TSIZE]) -> Result<(), ArrayError> {
105        self.inner.try_push_array(arr)
106    }
107
108    #[inline(always)]
109    fn try_push_slice(&mut self, slice: &[T]) -> Result<(), ArrayError>
110    where
111        T: Clone,
112    {
113        self.inner.try_push_slice(slice)
114    }
115
116    #[inline(always)]
117    fn try_pop(&mut self) -> Result<T, crate::errors::ArrayIsEmptyError> {
118        self.inner.try_pop()
119    }
120
121    #[inline(always)]
122    fn as_slice_mut(&mut self) -> &mut [T] {
123        self.inner.as_slice_mut()
124    }
125}
126
127impl<T: PartialEq, TAllocator: Allocator> PartialEq for DynamicArray<T, TAllocator> {
128    fn eq(&self, other: &Self) -> bool {
129        self.as_slice() == other.as_slice()
130    }
131}
132
133impl<T: Eq, TAllocator: Allocator> Eq for DynamicArray<T, TAllocator> {}
134
135impl<T: Hash, TAllocator: Allocator> Hash for DynamicArray<T, TAllocator> {
136    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
137        self.as_slice().hash(state);
138    }
139}
140
141impl<T, TAllocator: Allocator> AsRef<[T]> for DynamicArray<T, TAllocator> {
142    fn as_ref(&self) -> &[T] {
143        self.as_slice()
144    }
145}
146
147impl<T, TAllocator: Allocator> AsMut<[T]> for DynamicArray<T, TAllocator> {
148    fn as_mut(&mut self) -> &mut [T] {
149        self.as_slice_mut()
150    }
151}
152
153impl<T, TAllocator: Allocator> Borrow<[T]> for DynamicArray<T, TAllocator> {
154    fn borrow(&self) -> &[T] {
155        self.as_slice()
156    }
157}
158
159impl<T, TAllocator: Allocator> BorrowMut<[T]> for DynamicArray<T, TAllocator> {
160    fn borrow_mut(&mut self) -> &mut [T] {
161        self.as_slice_mut()
162    }
163}
164
165impl<T, TAllocator: Allocator> core::ops::Index<Length> for DynamicArray<T, TAllocator> {
166    type Output = T;
167
168    #[inline(always)]
169    fn index(&self, index: Length) -> &Self::Output {
170        &self.as_slice()[index.as_usize()]
171    }
172}
173
174impl<T, TAllocator: Allocator> core::ops::IndexMut<Length> for DynamicArray<T, TAllocator> {
175    #[inline(always)]
176    fn index_mut(&mut self, index: Length) -> &mut Self::Output {
177        &mut self.as_slice_mut()[index.as_usize()]
178    }
179}