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 pub(crate) unsafe fn emplace_in(
248 &self,
249 target: &mut crate::item::owned::ItemCopyTarget,
250 ) -> InternalArray<'static> {
251 let len = self.len as usize;
252 if len == 0 {
253 return InternalArray::new();
254 }
255 let byte_size = len * size_of::<Item<'static>>();
256 let dst_ptr = unsafe { target.alloc_aligned(byte_size) }
258 .as_ptr()
259 .cast::<Item<'static>>();
260 for (i, item) in self.as_slice().iter().enumerate() {
261 let new_item = unsafe { item.emplace_in(target) };
262 unsafe { dst_ptr.add(i).write(new_item) };
264 }
265 InternalArray {
266 len: self.len,
267 cap: self.len,
268 ptr: unsafe { NonNull::new_unchecked(dst_ptr) },
270 }
271 }
272}
273
274impl std::fmt::Debug for InternalArray<'_> {
275 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
276 f.debug_list().entries(self.as_slice()).finish()
277 }
278}
279
280impl<'a, 'de> IntoIterator for &'a InternalArray<'de> {
281 type Item = &'a Item<'de>;
282 type IntoIter = std::slice::Iter<'a, Item<'de>>;
283
284 fn into_iter(self) -> Self::IntoIter {
285 self.as_slice().iter()
286 }
287}
288
289impl<'a, 'de> IntoIterator for &'a mut InternalArray<'de> {
290 type Item = &'a mut Item<'de>;
291 type IntoIter = std::slice::IterMut<'a, Item<'de>>;
292
293 fn into_iter(self) -> Self::IntoIter {
294 self.as_mut_slice().iter_mut()
295 }
296}
297
298pub(crate) struct InternalArrayIntoIter<'de> {
300 arr: InternalArray<'de>,
301 index: u32,
302}
303
304impl<'de> Iterator for InternalArrayIntoIter<'de> {
305 type Item = Item<'de>;
306
307 fn next(&mut self) -> Option<Self::Item> {
308 if self.index < self.arr.len {
309 let val = unsafe { self.arr.ptr.as_ptr().add(self.index as usize).read() };
312 self.index += 1;
313 Some(val)
314 } else {
315 None
316 }
317 }
318
319 fn size_hint(&self) -> (usize, Option<usize>) {
320 let remaining = (self.arr.len - self.index) as usize;
321 (remaining, Some(remaining))
322 }
323}
324
325impl<'de> ExactSizeIterator for InternalArrayIntoIter<'de> {}
326
327impl<'de> IntoIterator for InternalArray<'de> {
328 type Item = Item<'de>;
329 type IntoIter = InternalArrayIntoIter<'de>;
330
331 fn into_iter(self) -> Self::IntoIter {
332 InternalArrayIntoIter {
333 arr: self,
334 index: 0,
335 }
336 }
337}
338
339impl<'de> std::ops::Index<usize> for InternalArray<'de> {
340 type Output = MaybeItem<'de>;
341
342 #[inline]
343 fn index(&self, index: usize) -> &Self::Output {
344 if let Some(item) = self.get(index) {
345 return MaybeItem::from_ref(item);
346 }
347 &crate::item::NONE
348 }
349}
350
351#[repr(C)]
371pub struct Array<'de> {
372 pub(crate) value: InternalArray<'de>,
373 pub(crate) meta: ItemMetadata,
374}
375
376const _: () = assert!(std::mem::size_of::<Array<'_>>() == std::mem::size_of::<Item<'_>>());
377const _: () = assert!(std::mem::align_of::<Array<'_>>() == std::mem::align_of::<Item<'_>>());
378
379unsafe impl Send for Array<'_> {}
386unsafe impl Sync for Array<'_> {}
387
388unsafe impl Send for IntoIter<'_> {}
392unsafe impl Sync for IntoIter<'_> {}
393
394impl<'de> Array<'de> {
395 pub fn new() -> Self {
401 let mut meta = ItemMetadata::hints(TAG_ARRAY, FLAG_ARRAY);
402 meta.set_auto_style();
403 Self {
404 meta,
405 value: InternalArray::new(),
406 }
407 }
408
409 pub fn try_with_capacity(cap: usize, arena: &'de Arena) -> Option<Self> {
413 let cap: u32 = cap.try_into().ok()?;
414 let mut meta = ItemMetadata::hints(TAG_ARRAY, FLAG_ARRAY);
415 meta.set_auto_style();
416 Some(Self {
417 meta,
418 value: InternalArray::with_capacity(cap, arena),
419 })
420 }
421
422 #[cfg(test)]
424 pub(crate) fn new_spanned(span: Span) -> Self {
425 Self {
426 meta: ItemMetadata::spanned(TAG_ARRAY, FLAG_ARRAY, span.start, span.end),
427 value: InternalArray::new(),
428 }
429 }
430
431 #[cfg_attr(not(test), allow(dead_code))]
434 pub(crate) fn span_unchecked(&self) -> Span {
435 self.meta.span_unchecked()
436 }
437
438 pub fn span(&self) -> Span {
441 self.meta.span()
442 }
443
444 #[inline]
446 pub fn push(&mut self, value: Item<'de>, arena: &'de Arena) {
447 self.value.push(value, arena);
448 }
449
450 #[inline]
452 pub fn len(&self) -> usize {
453 self.value.len()
454 }
455
456 #[inline]
458 pub fn is_empty(&self) -> bool {
459 self.value.is_empty()
460 }
461
462 #[inline]
464 pub fn get(&self, index: usize) -> Option<&Item<'de>> {
465 self.value.get(index)
466 }
467
468 #[inline]
470 pub fn get_mut(&mut self, index: usize) -> Option<&mut Item<'de>> {
471 self.value.get_mut(index)
472 }
473
474 #[inline]
481 pub fn remove(&mut self, index: usize) -> Item<'de> {
482 self.value.remove(index)
483 }
484
485 #[inline]
487 pub fn pop(&mut self) -> Option<Item<'de>> {
488 self.value.pop()
489 }
490
491 #[inline]
493 pub fn last_mut(&mut self) -> Option<&mut Item<'de>> {
494 self.value.last_mut()
495 }
496
497 #[inline]
499 pub fn iter(&self) -> std::slice::Iter<'_, Item<'de>> {
500 self.value.iter()
501 }
502
503 #[inline]
505 pub fn as_slice(&self) -> &[Item<'de>] {
506 self.value.as_slice()
507 }
508
509 #[inline]
511 pub fn as_mut_slice(&mut self) -> &mut [Item<'de>] {
512 self.value.as_mut_slice()
513 }
514
515 pub fn as_item(&self) -> &Item<'de> {
517 unsafe { &*(self as *const Array<'de>).cast::<Item<'de>>() }
524 }
525
526 pub fn into_item(self) -> Item<'de> {
528 unsafe { std::mem::transmute(self) }
532 }
533
534 #[inline]
536 pub fn style(&self) -> ArrayStyle {
537 match self.meta.flag() {
538 FLAG_AOT => ArrayStyle::Header,
539 _ => ArrayStyle::Inline,
540 }
541 }
542
543 #[inline]
549 pub fn set_style(&mut self, kind: ArrayStyle) {
550 let flag = match kind {
551 ArrayStyle::Inline => FLAG_ARRAY,
552 ArrayStyle::Header => FLAG_AOT,
553 };
554 self.meta.set_flag(flag);
555 self.meta.clear_auto_style();
556 }
557
558 pub fn clone_in(&self, arena: &'de Arena) -> Array<'de> {
561 Array {
562 value: self.value.clone_in(arena),
563 meta: self.meta,
564 }
565 }
566}
567
568impl<'de> Default for Array<'de> {
569 fn default() -> Self {
570 Self::new()
571 }
572}
573
574impl std::fmt::Debug for Array<'_> {
575 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
576 self.value.fmt(f)
577 }
578}
579
580impl<'de> std::ops::Index<usize> for Array<'de> {
581 type Output = MaybeItem<'de>;
582
583 #[inline]
584 fn index(&self, index: usize) -> &Self::Output {
585 if let Some(item) = self.value.get(index) {
586 return MaybeItem::from_ref(item);
587 }
588 &crate::item::NONE
589 }
590}
591
592impl<'a, 'de> IntoIterator for &'a Array<'de> {
593 type Item = &'a Item<'de>;
594 type IntoIter = std::slice::Iter<'a, Item<'de>>;
595
596 fn into_iter(self) -> Self::IntoIter {
597 self.value.as_slice().iter()
598 }
599}
600
601impl<'a, 'de> IntoIterator for &'a mut Array<'de> {
602 type Item = &'a mut Item<'de>;
603 type IntoIter = std::slice::IterMut<'a, Item<'de>>;
604
605 fn into_iter(self) -> Self::IntoIter {
606 self.value.as_mut_slice().iter_mut()
607 }
608}
609
610pub struct IntoIter<'de> {
612 arr: InternalArray<'de>,
613 index: u32,
614}
615
616impl<'de> Iterator for IntoIter<'de> {
617 type Item = Item<'de>;
618
619 fn next(&mut self) -> Option<Self::Item> {
620 if self.index < self.arr.len {
621 let val = unsafe { self.arr.ptr.as_ptr().add(self.index as usize).read() };
624 self.index += 1;
625 Some(val)
626 } else {
627 None
628 }
629 }
630
631 fn size_hint(&self) -> (usize, Option<usize>) {
632 let remaining = (self.arr.len - self.index) as usize;
633 (remaining, Some(remaining))
634 }
635}
636
637impl<'de> ExactSizeIterator for IntoIter<'de> {}
638
639impl<'de> IntoIterator for Array<'de> {
640 type Item = Item<'de>;
641 type IntoIter = IntoIter<'de>;
642
643 fn into_iter(self) -> Self::IntoIter {
644 IntoIter {
645 arr: self.value,
646 index: 0,
647 }
648 }
649}