1#[cfg(test)]
2#[path = "./array_tests.rs"]
3mod tests;
4
5use crate::MaybeItem;
6use crate::Span;
7use crate::arena::Arena;
8use crate::item::{ArrayStyle, FLAG_AOT, FLAG_ARRAY, Item, ItemMetadata, TAG_ARRAY};
9use std::mem::size_of;
10use std::ptr::NonNull;
11
12const MIN_CAP: u32 = 4;
13
14#[repr(C, align(8))]
15pub(crate) struct InternalArray<'de> {
16 pub(super) len: u32,
17 pub(super) cap: u32,
18 pub(super) ptr: NonNull<Item<'de>>,
19}
20
21impl<'de> Default for InternalArray<'de> {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27impl<'de> InternalArray<'de> {
28 #[inline]
29 pub(crate) fn new() -> Self {
30 Self {
31 len: 0,
32 cap: 0,
33 ptr: NonNull::dangling(),
34 }
35 }
36
37 pub(crate) fn with_capacity(cap: u32, arena: &'de Arena) -> Self {
38 let mut arr = Self::new();
39 if cap > 0 {
40 arr.grow_to(cap, arena);
41 }
42 arr
43 }
44
45 pub(crate) fn with_single(value: Item<'de>, arena: &'de Arena) -> Self {
46 let mut arr = Self::with_capacity(MIN_CAP, arena);
47 unsafe {
50 arr.ptr.as_ptr().write(value);
51 }
52 arr.len = 1;
53 arr
54 }
55
56 #[inline]
57 pub(crate) fn push(&mut self, value: Item<'de>, arena: &'de Arena) {
58 let len = self.len;
59 if len == self.cap {
60 self.grow(arena);
61 }
62 unsafe {
64 self.ptr.as_ptr().add(len as usize).write(value);
65 }
66 self.len = len + 1;
67 }
68
69 #[inline]
70 pub(crate) fn len(&self) -> usize {
71 self.len as usize
72 }
73
74 #[inline]
75 pub(crate) fn is_empty(&self) -> bool {
76 self.len == 0
77 }
78
79 #[inline]
80 pub(crate) fn get(&self, index: usize) -> Option<&Item<'de>> {
81 if index < self.len as usize {
82 Some(unsafe { &*self.ptr.as_ptr().add(index) })
85 } else {
86 None
87 }
88 }
89
90 #[inline]
91 pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut Item<'de>> {
92 if index < self.len as usize {
93 Some(unsafe { &mut *self.ptr.as_ptr().add(index) })
95 } else {
96 None
97 }
98 }
99
100 pub(crate) fn remove(&mut self, index: usize) -> Item<'de> {
101 assert!(index < self.len as usize, "index out of bounds");
102 let len = self.len as usize;
103 unsafe {
106 let ptr = self.ptr.as_ptr().add(index);
107 let removed = ptr.read();
108 std::ptr::copy(ptr.add(1), ptr, len - index - 1);
109 self.len -= 1;
110 removed
111 }
112 }
113
114 #[inline]
115 pub(crate) fn pop(&mut self) -> Option<Item<'de>> {
116 if self.len == 0 {
117 None
118 } else {
119 self.len -= 1;
120 Some(unsafe { self.ptr.as_ptr().add(self.len as usize).read() })
123 }
124 }
125
126 #[inline]
127 pub(crate) fn last_mut(&mut self) -> Option<&mut Item<'de>> {
128 if self.len == 0 {
129 None
130 } else {
131 Some(unsafe { &mut *self.ptr.as_ptr().add(self.len as usize - 1) })
133 }
134 }
135
136 #[inline]
137 pub(crate) fn iter(&self) -> std::slice::Iter<'_, Item<'de>> {
138 self.as_slice().iter()
139 }
140
141 #[inline]
142 pub(crate) fn as_slice(&self) -> &[Item<'de>] {
143 if self.len == 0 {
144 &[]
145 } else {
146 unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len as usize) }
149 }
150 }
151
152 #[inline]
153 pub(crate) fn as_mut_slice(&mut self) -> &mut [Item<'de>] {
154 if self.len == 0 {
155 &mut []
156 } else {
157 unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len as usize) }
159 }
160 }
161
162 #[cold]
163 fn grow(&mut self, arena: &'de Arena) {
164 let new_cap = if self.cap == 0 {
165 MIN_CAP
166 } else {
167 self.cap.checked_mul(2).expect("capacity overflow")
168 };
169 self.grow_to(new_cap, arena);
170 }
171
172 fn grow_to(&mut self, new_cap: u32, arena: &'de Arena) {
173 #[cfg(target_pointer_width = "32")]
175 let new_size = (new_cap as usize)
176 .checked_mul(size_of::<Item<'_>>())
177 .expect("capacity overflow");
178 #[cfg(not(target_pointer_width = "32"))]
179 let new_size = new_cap as usize * size_of::<Item<'_>>();
180 if self.cap > 0 {
181 let old_size = self.cap as usize * size_of::<Item<'_>>();
182 self.ptr = unsafe { arena.realloc(self.ptr.cast(), old_size, new_size).cast() };
184 } else {
185 self.ptr = arena.alloc(new_size).cast();
186 }
187 self.cap = new_cap;
188 }
189
190 pub(crate) fn clone_in(&self, arena: &'de Arena) -> Self {
193 let len = self.len as usize;
194 if len == 0 {
195 return Self::new();
196 }
197 let size = len * size_of::<Item<'de>>();
198 let dst: NonNull<Item<'de>> = arena.alloc(size).cast();
199 let src = self.ptr.as_ptr();
200 let dst_ptr = dst.as_ptr();
201
202 let mut run_start = 0;
203 for i in 0..len {
204 if unsafe { !(*src.add(i)).is_scalar() } {
206 if run_start < i {
207 unsafe {
210 std::ptr::copy_nonoverlapping(
211 src.add(run_start),
212 dst_ptr.add(run_start),
213 i - run_start,
214 );
215 }
216 }
217 unsafe {
219 dst_ptr.add(i).write((*src.add(i)).clone_in(arena));
220 }
221 run_start = i + 1;
222 }
223 }
224 if run_start < len {
225 unsafe {
226 std::ptr::copy_nonoverlapping(
227 src.add(run_start),
228 dst_ptr.add(run_start),
229 len - run_start,
230 );
231 }
232 }
233
234 Self {
235 len: self.len,
236 cap: self.len,
237 ptr: dst,
238 }
239 }
240}
241
242impl std::fmt::Debug for InternalArray<'_> {
243 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
244 f.debug_list().entries(self.as_slice()).finish()
245 }
246}
247
248impl<'a, 'de> IntoIterator for &'a InternalArray<'de> {
249 type Item = &'a Item<'de>;
250 type IntoIter = std::slice::Iter<'a, Item<'de>>;
251
252 fn into_iter(self) -> Self::IntoIter {
253 self.as_slice().iter()
254 }
255}
256
257impl<'a, 'de> IntoIterator for &'a mut InternalArray<'de> {
258 type Item = &'a mut Item<'de>;
259 type IntoIter = std::slice::IterMut<'a, Item<'de>>;
260
261 fn into_iter(self) -> Self::IntoIter {
262 self.as_mut_slice().iter_mut()
263 }
264}
265
266pub(crate) struct InternalArrayIntoIter<'de> {
268 arr: InternalArray<'de>,
269 index: u32,
270}
271
272impl<'de> Iterator for InternalArrayIntoIter<'de> {
273 type Item = Item<'de>;
274
275 fn next(&mut self) -> Option<Self::Item> {
276 if self.index < self.arr.len {
277 let val = unsafe { self.arr.ptr.as_ptr().add(self.index as usize).read() };
280 self.index += 1;
281 Some(val)
282 } else {
283 None
284 }
285 }
286
287 fn size_hint(&self) -> (usize, Option<usize>) {
288 let remaining = (self.arr.len - self.index) as usize;
289 (remaining, Some(remaining))
290 }
291}
292
293impl<'de> ExactSizeIterator for InternalArrayIntoIter<'de> {}
294
295impl<'de> IntoIterator for InternalArray<'de> {
296 type Item = Item<'de>;
297 type IntoIter = InternalArrayIntoIter<'de>;
298
299 fn into_iter(self) -> Self::IntoIter {
300 InternalArrayIntoIter {
301 arr: self,
302 index: 0,
303 }
304 }
305}
306
307impl<'de> std::ops::Index<usize> for InternalArray<'de> {
308 type Output = MaybeItem<'de>;
309
310 #[inline]
311 fn index(&self, index: usize) -> &Self::Output {
312 if let Some(item) = self.get(index) {
313 return MaybeItem::from_ref(item);
314 }
315 &crate::item::NONE
316 }
317}
318
319#[repr(C)]
339pub struct Array<'de> {
340 pub(crate) value: InternalArray<'de>,
341 pub(crate) meta: ItemMetadata,
342}
343
344const _: () = assert!(std::mem::size_of::<Array<'_>>() == std::mem::size_of::<Item<'_>>());
345const _: () = assert!(std::mem::align_of::<Array<'_>>() == std::mem::align_of::<Item<'_>>());
346
347impl<'de> Array<'de> {
348 pub fn new() -> Self {
354 let mut meta = ItemMetadata::hints(TAG_ARRAY, FLAG_ARRAY);
355 meta.set_auto_style();
356 Self {
357 meta,
358 value: InternalArray::new(),
359 }
360 }
361
362 pub fn try_with_capacity(cap: usize, arena: &'de Arena) -> Option<Self> {
366 let cap: u32 = cap.try_into().ok()?;
367 let mut meta = ItemMetadata::hints(TAG_ARRAY, FLAG_ARRAY);
368 meta.set_auto_style();
369 Some(Self {
370 meta,
371 value: InternalArray::with_capacity(cap, arena),
372 })
373 }
374
375 #[cfg(test)]
377 pub(crate) fn new_spanned(span: Span) -> Self {
378 Self {
379 meta: ItemMetadata::spanned(TAG_ARRAY, FLAG_ARRAY, span.start, span.end),
380 value: InternalArray::new(),
381 }
382 }
383
384 #[cfg_attr(not(test), allow(dead_code))]
387 pub(crate) fn span_unchecked(&self) -> Span {
388 self.meta.span_unchecked()
389 }
390
391 pub fn span(&self) -> Span {
394 self.meta.span()
395 }
396
397 #[inline]
399 pub fn push(&mut self, value: Item<'de>, arena: &'de Arena) {
400 self.value.push(value, arena);
401 }
402
403 #[inline]
405 pub fn len(&self) -> usize {
406 self.value.len()
407 }
408
409 #[inline]
411 pub fn is_empty(&self) -> bool {
412 self.value.is_empty()
413 }
414
415 #[inline]
417 pub fn get(&self, index: usize) -> Option<&Item<'de>> {
418 self.value.get(index)
419 }
420
421 #[inline]
423 pub fn get_mut(&mut self, index: usize) -> Option<&mut Item<'de>> {
424 self.value.get_mut(index)
425 }
426
427 #[inline]
434 pub fn remove(&mut self, index: usize) -> Item<'de> {
435 self.value.remove(index)
436 }
437
438 #[inline]
440 pub fn pop(&mut self) -> Option<Item<'de>> {
441 self.value.pop()
442 }
443
444 #[inline]
446 pub fn last_mut(&mut self) -> Option<&mut Item<'de>> {
447 self.value.last_mut()
448 }
449
450 #[inline]
452 pub fn iter(&self) -> std::slice::Iter<'_, Item<'de>> {
453 self.value.iter()
454 }
455
456 #[inline]
458 pub fn as_slice(&self) -> &[Item<'de>] {
459 self.value.as_slice()
460 }
461
462 #[inline]
464 pub fn as_mut_slice(&mut self) -> &mut [Item<'de>] {
465 self.value.as_mut_slice()
466 }
467
468 pub fn as_item(&self) -> &Item<'de> {
470 unsafe { &*(self as *const Array<'de>).cast::<Item<'de>>() }
477 }
478
479 pub fn into_item(self) -> Item<'de> {
481 unsafe { std::mem::transmute(self) }
485 }
486
487 #[inline]
489 pub fn style(&self) -> ArrayStyle {
490 match self.meta.flag() {
491 FLAG_AOT => ArrayStyle::Header,
492 _ => ArrayStyle::Inline,
493 }
494 }
495
496 #[inline]
498 pub fn set_style(&mut self, kind: ArrayStyle) {
499 let flag = match kind {
500 ArrayStyle::Inline => FLAG_ARRAY,
501 ArrayStyle::Header => FLAG_AOT,
502 };
503 self.meta.set_flag(flag);
504 self.meta.clear_auto_style();
505 }
506
507 pub fn clone_in(&self, arena: &'de Arena) -> Array<'de> {
510 Array {
511 value: self.value.clone_in(arena),
512 meta: self.meta,
513 }
514 }
515}
516
517impl<'de> Default for Array<'de> {
518 fn default() -> Self {
519 Self::new()
520 }
521}
522
523impl std::fmt::Debug for Array<'_> {
524 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
525 self.value.fmt(f)
526 }
527}
528
529impl<'de> std::ops::Index<usize> for Array<'de> {
530 type Output = MaybeItem<'de>;
531
532 #[inline]
533 fn index(&self, index: usize) -> &Self::Output {
534 if let Some(item) = self.value.get(index) {
535 return MaybeItem::from_ref(item);
536 }
537 &crate::item::NONE
538 }
539}
540
541impl<'a, 'de> IntoIterator for &'a Array<'de> {
542 type Item = &'a Item<'de>;
543 type IntoIter = std::slice::Iter<'a, Item<'de>>;
544
545 fn into_iter(self) -> Self::IntoIter {
546 self.value.as_slice().iter()
547 }
548}
549
550impl<'a, 'de> IntoIterator for &'a mut Array<'de> {
551 type Item = &'a mut Item<'de>;
552 type IntoIter = std::slice::IterMut<'a, Item<'de>>;
553
554 fn into_iter(self) -> Self::IntoIter {
555 self.value.as_mut_slice().iter_mut()
556 }
557}
558
559pub struct IntoIter<'de> {
561 arr: InternalArray<'de>,
562 index: u32,
563}
564
565impl<'de> Iterator for IntoIter<'de> {
566 type Item = Item<'de>;
567
568 fn next(&mut self) -> Option<Self::Item> {
569 if self.index < self.arr.len {
570 let val = unsafe { self.arr.ptr.as_ptr().add(self.index as usize).read() };
573 self.index += 1;
574 Some(val)
575 } else {
576 None
577 }
578 }
579
580 fn size_hint(&self) -> (usize, Option<usize>) {
581 let remaining = (self.arr.len - self.index) as usize;
582 (remaining, Some(remaining))
583 }
584}
585
586impl<'de> ExactSizeIterator for IntoIter<'de> {}
587
588impl<'de> IntoIterator for Array<'de> {
589 type Item = Item<'de>;
590 type IntoIter = IntoIter<'de>;
591
592 fn into_iter(self) -> Self::IntoIter {
593 IntoIter {
594 arr: self.value,
595 index: 0,
596 }
597 }
598}