1use std::alloc::{alloc, dealloc, realloc, Layout, LayoutError};
4use std::borrow::{Borrow, BorrowMut};
5use std::cmp::{self, Ordering};
6use std::fmt::{self, Debug, Formatter};
7use std::hash::Hash;
8use std::iter::FromIterator;
9use std::ops::{Deref, DerefMut, Index, IndexMut};
10use std::slice::SliceIndex;
11
12use crate::thin::{ThinMut, ThinMutExt, ThinRef, ThinRefExt};
13
14use super::value::{IValue, TypeTag};
15
16#[repr(C)]
17#[repr(align(4))]
18struct Header {
19 len: usize,
20 cap: usize,
21}
22
23trait HeaderRef<'a>: ThinRefExt<'a, Header> {
24 fn array_ptr(&self) -> *const IValue {
25 unsafe { self.ptr().add(1).cast::<IValue>() }
27 }
28 fn items_slice(&self) -> &'a [IValue] {
29 unsafe { std::slice::from_raw_parts(self.array_ptr(), self.len) }
31 }
32}
33
34trait HeaderMut<'a>: ThinMutExt<'a, Header> {
35 fn array_ptr_mut(mut self) -> *mut IValue {
36 unsafe { self.ptr_mut().add(1).cast::<IValue>() }
38 }
39 fn items_slice_mut(self) -> &'a mut [IValue] {
40 let len = self.len;
42 unsafe { std::slice::from_raw_parts_mut(self.array_ptr_mut(), len) }
43 }
44 unsafe fn push(&mut self, item: IValue) {
46 let index = self.len;
47 self.reborrow().array_ptr_mut().add(index).write(item);
48 self.len += 1;
49 }
50 fn pop(&mut self) -> Option<IValue> {
51 if self.len == 0 {
52 None
53 } else {
54 self.len -= 1;
55 let index = self.len;
56
57 unsafe { Some(self.reborrow().array_ptr_mut().add(index).read()) }
59 }
60 }
61}
62
63impl<'a, T: ThinRefExt<'a, Header>> HeaderRef<'a> for T {}
64impl<'a, T: ThinMutExt<'a, Header>> HeaderMut<'a> for T {}
65
66pub struct IntoIter {
68 reversed_array: IArray,
69}
70
71impl Iterator for IntoIter {
72 type Item = IValue;
73
74 fn next(&mut self) -> Option<Self::Item> {
75 self.reversed_array.pop()
76 }
77}
78
79impl ExactSizeIterator for IntoIter {
80 fn len(&self) -> usize {
81 self.reversed_array.len()
82 }
83}
84
85impl Debug for IntoIter {
86 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
87 f.debug_struct("IntoIter")
88 .field("reversed_array", &self.reversed_array)
89 .finish()
90 }
91}
92
93#[repr(transparent)]
97#[derive(Clone, size_of::SizeOf, Ord)]
98pub struct IArray(pub(crate) IValue);
99
100value_subtype_impls!(IArray, into_array, as_array, as_array_mut);
101
102static EMPTY_HEADER: Header = Header { len: 0, cap: 0 };
103
104impl IArray {
105 fn layout(cap: usize) -> Result<Layout, LayoutError> {
106 Ok(Layout::new::<Header>()
107 .extend(Layout::array::<usize>(cap)?)?
108 .0
109 .pad_to_align())
110 }
111
112 fn alloc(cap: usize) -> *mut Header {
113 unsafe {
114 let ptr = alloc(Self::layout(cap).unwrap()).cast::<Header>();
115 ptr.write(Header { len: 0, cap });
116 ptr
117 }
118 }
119
120 fn realloc(ptr: *mut Header, new_cap: usize) -> *mut Header {
121 unsafe {
122 let old_layout = Self::layout((*ptr).cap).unwrap();
123 let new_layout = Self::layout(new_cap).unwrap();
124 let ptr = realloc(ptr.cast::<u8>(), old_layout, new_layout.size()).cast::<Header>();
125 (*ptr).cap = new_cap;
126 ptr
127 }
128 }
129
130 fn dealloc(ptr: *mut Header) {
131 unsafe {
132 let layout = Self::layout((*ptr).cap).unwrap();
133 dealloc(ptr.cast(), layout);
134 }
135 }
136
137 #[must_use]
139 pub fn new() -> Self {
140 unsafe { IArray(IValue::new_ref(&EMPTY_HEADER, TypeTag::ArrayOrFalse)) }
141 }
142
143 #[must_use]
146 pub fn with_capacity(cap: usize) -> Self {
147 if cap == 0 {
148 Self::new()
149 } else {
150 IArray(unsafe { IValue::new_ptr(Self::alloc(cap).cast(), TypeTag::ArrayOrFalse) })
151 }
152 }
153
154 fn header(&self) -> ThinRef<Header> {
155 unsafe { ThinRef::new(self.0.ptr().cast()) }
156 }
157
158 unsafe fn header_mut(&mut self) -> ThinMut<Header> {
160 ThinMut::new(self.0.ptr().cast())
161 }
162
163 fn is_static(&self) -> bool {
164 self.capacity() == 0
165 }
166 #[must_use]
169 pub fn capacity(&self) -> usize {
170 self.header().cap
171 }
172
173 #[must_use]
175 pub fn len(&self) -> usize {
176 self.header().len
177 }
178
179 #[must_use]
181 pub fn is_empty(&self) -> bool {
182 self.len() == 0
183 }
184
185 #[must_use]
187 pub fn as_slice(&self) -> &[IValue] {
188 self.header().items_slice()
189 }
190
191 pub fn as_mut_slice(&mut self) -> &mut [IValue] {
193 if self.is_static() {
194 &mut []
195 } else {
196 unsafe { self.header_mut().items_slice_mut() }
197 }
198 }
199 fn resize_internal(&mut self, cap: usize) {
200 if self.is_static() || cap == 0 {
201 *self = Self::with_capacity(cap);
202 } else {
203 unsafe {
204 let new_ptr = Self::realloc(self.0.ptr().cast(), cap);
205 self.0.set_ptr(new_ptr.cast());
206 }
207 }
208 }
209
210 pub fn reserve(&mut self, additional: usize) {
212 let hd = self.header();
213 let current_capacity = hd.cap;
214 let desired_capacity = hd.len.checked_add(additional).unwrap();
215 if current_capacity >= desired_capacity {
216 return;
217 }
218 self.resize_internal(cmp::max(current_capacity * 2, desired_capacity.max(4)));
219 }
220
221 pub fn truncate(&mut self, len: usize) {
224 if self.is_static() {
225 return;
226 }
227 unsafe {
228 let mut hd = self.header_mut();
229 while hd.len > len {
230 hd.pop();
231 }
232 }
233 }
234
235 pub fn clear(&mut self) {
237 self.truncate(0);
238 }
239
240 pub fn insert(&mut self, index: usize, item: impl Into<IValue>) {
245 self.reserve(1);
246
247 unsafe {
248 let mut hd = self.header_mut();
250 assert!(index <= hd.len);
251
252 hd.push(item.into());
254 if index < hd.len {
255 hd.items_slice_mut()[index..].rotate_right(1);
256 }
257 }
258 }
259
260 pub fn remove(&mut self, index: usize) -> Option<IValue> {
269 if index < self.len() {
270 unsafe {
272 let mut hd = self.header_mut();
273 hd.reborrow().items_slice_mut()[index..].rotate_left(1);
274 hd.pop()
275 }
276 } else {
277 None
278 }
279 }
280
281 pub fn swap_remove(&mut self, index: usize) -> Option<IValue> {
290 if index < self.len() {
291 unsafe {
293 let mut hd = self.header_mut();
294 let last_index = hd.len - 1;
295 hd.reborrow().items_slice_mut().swap(index, last_index);
296 hd.pop()
297 }
298 } else {
299 None
300 }
301 }
302
303 pub fn push(&mut self, item: impl Into<IValue>) {
305 self.reserve(1);
306 unsafe {
308 self.header_mut().push(item.into());
309 }
310 }
311
312 pub fn pop(&mut self) -> Option<IValue> {
315 if self.is_static() {
316 None
317 } else {
318 unsafe { self.header_mut().pop() }
320 }
321 }
322
323 pub fn shrink_to_fit(&mut self) {
326 self.resize_internal(self.len());
327 }
328
329 pub(crate) fn clone_impl(&self) -> IValue {
330 let src = self.header().items_slice();
331 let l = src.len();
332 let mut res = Self::with_capacity(l);
333
334 if l > 0 {
335 unsafe {
336 let mut hd = res.header_mut();
338 for v in src {
339 hd.push(v.clone());
341 }
342 }
343 }
344 res.0
345 }
346 pub(crate) fn drop_impl(&mut self) {
347 self.clear();
348 if !self.is_static() {
349 unsafe {
350 Self::dealloc(self.0.ptr().cast());
351 self.0.set_ref(&EMPTY_HEADER);
352 }
353 }
354 }
355}
356
357impl IntoIterator for IArray {
358 type Item = IValue;
359 type IntoIter = IntoIter;
360
361 fn into_iter(mut self) -> Self::IntoIter {
362 self.reverse();
363 IntoIter {
364 reversed_array: self,
365 }
366 }
367}
368
369impl Deref for IArray {
370 type Target = [IValue];
371
372 fn deref(&self) -> &Self::Target {
373 self.as_slice()
374 }
375}
376
377impl DerefMut for IArray {
378 fn deref_mut(&mut self) -> &mut Self::Target {
379 self.as_mut_slice()
380 }
381}
382
383impl Borrow<[IValue]> for IArray {
384 fn borrow(&self) -> &[IValue] {
385 self.as_slice()
386 }
387}
388
389impl BorrowMut<[IValue]> for IArray {
390 fn borrow_mut(&mut self) -> &mut [IValue] {
391 self.as_mut_slice()
392 }
393}
394
395impl Hash for IArray {
396 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
397 self.as_slice().hash(state);
398 }
399}
400
401impl<U: Into<IValue>> Extend<U> for IArray {
402 fn extend<T: IntoIterator<Item = U>>(&mut self, iter: T) {
403 let iter = iter.into_iter();
404 self.reserve(iter.size_hint().0);
405 for v in iter {
406 self.push(v);
407 }
408 }
409}
410
411impl<U: Into<IValue>> FromIterator<U> for IArray {
412 fn from_iter<T: IntoIterator<Item = U>>(iter: T) -> Self {
413 let mut res = IArray::new();
414 res.extend(iter);
415 res
416 }
417}
418
419impl AsRef<[IValue]> for IArray {
420 fn as_ref(&self) -> &[IValue] {
421 self.as_slice()
422 }
423}
424
425impl PartialEq for IArray {
426 fn eq(&self, other: &Self) -> bool {
427 if self.0.raw_eq(&other.0) {
428 true
429 } else {
430 self.as_slice() == other.as_slice()
431 }
432 }
433}
434
435impl Eq for IArray {}
436impl PartialOrd for IArray {
437 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
438 if self.0.raw_eq(&other.0) {
439 Some(Ordering::Equal)
440 } else {
441 self.as_slice().partial_cmp(other.as_slice())
442 }
443 }
444}
445
446impl<I: SliceIndex<[IValue]>> Index<I> for IArray {
447 type Output = I::Output;
448
449 #[inline]
450 fn index(&self, index: I) -> &Self::Output {
451 Index::index(self.as_slice(), index)
452 }
453}
454
455impl<I: SliceIndex<[IValue]>> IndexMut<I> for IArray {
456 #[inline]
457 fn index_mut(&mut self, index: I) -> &mut Self::Output {
458 IndexMut::index_mut(self.as_mut_slice(), index)
459 }
460}
461
462impl Debug for IArray {
463 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
464 Debug::fmt(self.as_slice(), f)
465 }
466}
467
468impl<T: Into<IValue>> From<Vec<T>> for IArray {
469 fn from(other: Vec<T>) -> Self {
470 let mut res = IArray::with_capacity(other.len());
471 res.extend(other.into_iter().map(Into::into));
472 res
473 }
474}
475
476impl<T: Into<IValue> + Clone> From<&[T]> for IArray {
477 fn from(other: &[T]) -> Self {
478 let mut res = IArray::with_capacity(other.len());
479 res.extend(other.iter().cloned().map(Into::into));
480 res
481 }
482}
483
484impl<'a> IntoIterator for &'a IArray {
485 type Item = &'a IValue;
486 type IntoIter = std::slice::Iter<'a, IValue>;
487
488 fn into_iter(self) -> Self::IntoIter {
489 self.iter()
490 }
491}
492
493impl<'a> IntoIterator for &'a mut IArray {
494 type Item = &'a mut IValue;
495 type IntoIter = std::slice::IterMut<'a, IValue>;
496
497 fn into_iter(self) -> Self::IntoIter {
498 self.iter_mut()
499 }
500}
501
502impl Default for IArray {
503 fn default() -> Self {
504 Self::new()
505 }
506}
507
508#[cfg(test)]
509mod tests {
510 use super::*;
511
512 #[mockalloc::test]
513 fn can_create() {
514 let x = IArray::new();
515 let y = IArray::with_capacity(10);
516
517 assert_eq!(x, y);
518 }
519
520 #[mockalloc::test]
521 fn can_collect() {
522 let x = vec![IValue::NULL, IValue::TRUE, IValue::FALSE];
523 let y: IArray = x.iter().cloned().collect();
524
525 assert_eq!(x.as_slice(), y.as_slice());
526 }
527
528 #[mockalloc::test]
529 fn can_push_insert() {
530 let mut x = IArray::new();
531 x.insert(0, IValue::NULL);
532 x.push(IValue::TRUE);
533 x.insert(1, IValue::FALSE);
534
535 assert_eq!(x.as_slice(), &[IValue::NULL, IValue::FALSE, IValue::TRUE]);
536 }
537
538 #[mockalloc::test]
539 fn can_nest() {
540 let x: IArray = vec![IValue::NULL, IValue::TRUE, IValue::FALSE].into();
541 let y: IArray = vec![
542 IValue::NULL,
543 x.clone().into(),
544 IValue::FALSE,
545 x.clone().into(),
546 ]
547 .into();
548
549 assert_eq!(&y[1], x.as_ref());
550 }
551
552 #[mockalloc::test]
553 fn can_pop_remove() {
554 let mut x: IArray = vec![IValue::NULL, IValue::TRUE, IValue::FALSE].into();
555 assert_eq!(x.remove(1), Some(IValue::TRUE));
556 assert_eq!(x.pop(), Some(IValue::FALSE));
557
558 assert_eq!(x.as_slice(), &[IValue::NULL]);
559 }
560
561 #[mockalloc::test]
562 fn can_swap_remove() {
563 let mut x: IArray = vec![IValue::NULL, IValue::TRUE, IValue::FALSE].into();
564 assert_eq!(x.swap_remove(0), Some(IValue::NULL));
565
566 assert_eq!(x.as_slice(), &[IValue::FALSE, IValue::TRUE]);
567 }
568
569 #[mockalloc::test]
570 fn can_index() {
571 let mut x: IArray = vec![IValue::NULL, IValue::TRUE, IValue::FALSE].into();
572 assert_eq!(x[1], IValue::TRUE);
573 x[1] = IValue::FALSE;
574 assert_eq!(x[1], IValue::FALSE);
575 }
576
577 #[mockalloc::test]
578 fn can_truncate_and_shrink() {
579 let mut x: IArray =
580 vec![IValue::NULL, IValue::TRUE, IArray::with_capacity(10).into()].into();
581 x.truncate(2);
582 assert_eq!(x.len(), 2);
583 assert_eq!(x.capacity(), 3);
584 x.shrink_to_fit();
585 assert_eq!(x.len(), 2);
586 assert_eq!(x.capacity(), 2);
587 }
588
589 #[cfg(not(miri))]
591 #[mockalloc::test]
592 fn stress_test() {
593 use rand::prelude::*;
594
595 for i in 0..10 {
596 let mut rng = StdRng::seed_from_u64(i);
598 let mut arr = IArray::new();
599
600 for j in 0..1000 {
601 let index = rng.gen_range(0..arr.len() + 1);
602 if rng.gen() {
603 arr.insert(index, j);
604 } else {
605 arr.remove(index);
606 }
607 }
608 }
609 }
610}