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