1#![allow(unsafe_code)]
2
3#[cfg(test)]
4#[path = "./array_tests.rs"]
5mod tests;
6
7use crate::MaybeItem;
8use crate::arena::Arena;
9use crate::value::Item;
10use std::mem::size_of;
11use std::ptr::NonNull;
12
13const MIN_CAP: u32 = 4;
14
15pub struct Array<'de> {
25 len: u32,
26 cap: u32,
27 ptr: NonNull<Item<'de>>,
28}
29
30impl<'de> Default for Array<'de> {
31 fn default() -> Self {
32 Self::new()
33 }
34}
35
36impl<'de> Array<'de> {
37 #[inline]
39 pub fn new() -> Self {
40 Self {
41 len: 0,
42 cap: 0,
43 ptr: NonNull::dangling(),
44 }
45 }
46
47 pub fn with_capacity(cap: u32, arena: &Arena) -> Self {
49 let mut arr = Self::new();
50 if cap > 0 {
51 arr.grow_to(cap, arena);
52 }
53 arr
54 }
55
56 pub fn with_single(value: Item<'de>, arena: &Arena) -> Self {
58 let mut arr = Self::with_capacity(MIN_CAP, arena);
59 unsafe {
60 arr.ptr.as_ptr().write(value);
61 }
62 arr.len = 1;
63 arr
64 }
65
66 #[inline]
68 pub fn push(&mut self, value: Item<'de>, arena: &Arena) {
69 let len = self.len;
70 if len == self.cap {
71 self.grow(arena);
72 }
73 unsafe {
74 self.ptr.as_ptr().add(len as usize).write(value);
75 }
76 self.len = len + 1;
77 }
78
79 #[inline]
81 pub fn len(&self) -> usize {
82 self.len as usize
83 }
84
85 #[inline]
87 pub fn is_empty(&self) -> bool {
88 self.len == 0
89 }
90
91 #[inline]
93 pub fn get(&self, index: usize) -> Option<&Item<'de>> {
94 if index < self.len as usize {
95 Some(unsafe { &*self.ptr.as_ptr().add(index) })
96 } else {
97 None
98 }
99 }
100
101 #[inline]
103 pub fn get_mut(&mut self, index: usize) -> Option<&mut Item<'de>> {
104 if index < self.len as usize {
105 Some(unsafe { &mut *self.ptr.as_ptr().add(index) })
106 } else {
107 None
108 }
109 }
110
111 #[inline]
113 pub fn pop(&mut self) -> Option<Item<'de>> {
114 if self.len == 0 {
115 None
116 } else {
117 self.len -= 1;
118 Some(unsafe { self.ptr.as_ptr().add(self.len as usize).read() })
119 }
120 }
121
122 #[inline]
124 pub fn last_mut(&mut self) -> Option<&mut Item<'de>> {
125 if self.len == 0 {
126 None
127 } else {
128 Some(unsafe { &mut *self.ptr.as_ptr().add(self.len as usize - 1) })
129 }
130 }
131
132 #[inline]
134 pub fn iter(&self) -> std::slice::Iter<'_, Item<'de>> {
135 self.as_slice().iter()
136 }
137
138 #[inline]
140 pub fn as_slice(&self) -> &[Item<'de>] {
141 if self.len == 0 {
142 &[]
143 } else {
144 unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len as usize) }
145 }
146 }
147
148 #[inline]
150 pub fn as_mut_slice(&mut self) -> &mut [Item<'de>] {
151 if self.len == 0 {
152 &mut []
153 } else {
154 unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len as usize) }
155 }
156 }
157
158 #[cold]
159 fn grow(&mut self, arena: &Arena) {
160 let new_cap = if self.cap == 0 {
161 MIN_CAP
162 } else {
163 self.cap.checked_mul(2).expect("capacity overflow")
164 };
165 self.grow_to(new_cap, arena);
166 }
167
168 fn grow_to(&mut self, new_cap: u32, arena: &Arena) {
169 let new_size = new_cap as usize * size_of::<Item<'_>>();
170 if self.cap > 0 {
171 let old_size = self.cap as usize * size_of::<Item<'_>>();
172 self.ptr = unsafe { arena.realloc(self.ptr.cast(), old_size, new_size).cast() };
174 } else {
175 self.ptr = arena.alloc(new_size).cast();
176 }
177 self.cap = new_cap;
178 }
179}
180
181impl std::fmt::Debug for Array<'_> {
182 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183 f.debug_list().entries(self.as_slice()).finish()
184 }
185}
186
187impl<'a, 'de> IntoIterator for &'a Array<'de> {
188 type Item = &'a Item<'de>;
189 type IntoIter = std::slice::Iter<'a, Item<'de>>;
190
191 fn into_iter(self) -> Self::IntoIter {
192 self.as_slice().iter()
193 }
194}
195
196impl<'a, 'de> IntoIterator for &'a mut Array<'de> {
197 type Item = &'a mut Item<'de>;
198 type IntoIter = std::slice::IterMut<'a, Item<'de>>;
199
200 fn into_iter(self) -> Self::IntoIter {
201 self.as_mut_slice().iter_mut()
202 }
203}
204
205pub struct IntoIter<'de> {
207 arr: Array<'de>,
208 index: u32,
209}
210
211impl<'de> Iterator for IntoIter<'de> {
212 type Item = Item<'de>;
213
214 fn next(&mut self) -> Option<Self::Item> {
215 if self.index < self.arr.len {
216 let val = unsafe { self.arr.ptr.as_ptr().add(self.index as usize).read() };
217 self.index += 1;
218 Some(val)
219 } else {
220 None
221 }
222 }
223
224 fn size_hint(&self) -> (usize, Option<usize>) {
225 let remaining = (self.arr.len - self.index) as usize;
226 (remaining, Some(remaining))
227 }
228}
229
230impl<'de> ExactSizeIterator for IntoIter<'de> {}
231
232impl<'de> IntoIterator for Array<'de> {
233 type Item = Item<'de>;
234 type IntoIter = IntoIter<'de>;
235
236 fn into_iter(self) -> Self::IntoIter {
237 IntoIter {
238 arr: self,
239 index: 0,
240 }
241 }
242}
243
244impl<'de> std::ops::Index<usize> for Array<'de> {
245 type Output = MaybeItem<'de>;
246
247 #[inline]
248 fn index(&self, index: usize) -> &Self::Output {
249 if let Some(item) = self.get(index) {
250 return MaybeItem::from_ref(item);
251 }
252 &crate::value::NONE
253 }
254}