1#[cfg(feature = "alloc")]
4use alloc::alloc::{Layout, alloc, dealloc, realloc};
5#[cfg(feature = "alloc")]
6use alloc::vec::Vec;
7use core::borrow::{Borrow, BorrowMut};
8use core::cmp::Ordering;
9use core::fmt::{self, Debug, Formatter};
10use core::hash::{Hash, Hasher};
11use core::iter::FromIterator;
12use core::ops::{Deref, DerefMut, Index, IndexMut};
13use core::slice::SliceIndex;
14use core::{cmp, ptr};
15
16use crate::value::{TypeTag, Value};
17
18#[repr(C, align(8))]
20struct ArrayHeader {
21 len: usize,
23 cap: usize,
25 }
27
28#[repr(transparent)]
33#[derive(Clone)]
34pub struct VArray(pub(crate) Value);
35
36impl VArray {
37 fn layout(cap: usize) -> Layout {
38 Layout::new::<ArrayHeader>()
39 .extend(Layout::array::<Value>(cap).unwrap())
40 .unwrap()
41 .0
42 .pad_to_align()
43 }
44
45 #[cfg(feature = "alloc")]
46 fn alloc(cap: usize) -> *mut ArrayHeader {
47 unsafe {
48 let layout = Self::layout(cap);
49 let ptr = alloc(layout).cast::<ArrayHeader>();
50 (*ptr).len = 0;
51 (*ptr).cap = cap;
52 ptr
53 }
54 }
55
56 #[cfg(feature = "alloc")]
57 fn realloc_ptr(ptr: *mut ArrayHeader, new_cap: usize) -> *mut ArrayHeader {
58 unsafe {
59 let old_cap = (*ptr).cap;
60 let old_layout = Self::layout(old_cap);
61 let new_layout = Self::layout(new_cap);
62 let new_ptr =
63 realloc(ptr.cast::<u8>(), old_layout, new_layout.size()).cast::<ArrayHeader>();
64 (*new_ptr).cap = new_cap;
65 new_ptr
66 }
67 }
68
69 #[cfg(feature = "alloc")]
70 fn dealloc_ptr(ptr: *mut ArrayHeader) {
71 unsafe {
72 let cap = (*ptr).cap;
73 let layout = Self::layout(cap);
74 dealloc(ptr.cast::<u8>(), layout);
75 }
76 }
77
78 fn header(&self) -> &ArrayHeader {
79 unsafe { &*(self.0.heap_ptr() as *const ArrayHeader) }
80 }
81
82 fn header_mut(&mut self) -> &mut ArrayHeader {
83 unsafe { &mut *(self.0.heap_ptr_mut() as *mut ArrayHeader) }
84 }
85
86 fn items_ptr(&self) -> *const Value {
87 unsafe { (self.0.heap_ptr() as *const ArrayHeader).add(1).cast() }
90 }
91
92 fn items_ptr_mut(&mut self) -> *mut Value {
93 unsafe { (self.0.heap_ptr_mut() as *mut ArrayHeader).add(1).cast() }
95 }
96
97 #[cfg(feature = "alloc")]
99 #[must_use]
100 pub fn new() -> Self {
101 Self::with_capacity(0)
102 }
103
104 #[cfg(feature = "alloc")]
106 #[must_use]
107 pub fn with_capacity(cap: usize) -> Self {
108 unsafe {
109 let ptr = Self::alloc(cap);
110 VArray(Value::new_ptr(ptr.cast(), TypeTag::ArrayOrTrue))
111 }
112 }
113
114 #[must_use]
116 pub fn len(&self) -> usize {
117 self.header().len
118 }
119
120 #[must_use]
122 pub fn is_empty(&self) -> bool {
123 self.len() == 0
124 }
125
126 #[must_use]
128 pub fn capacity(&self) -> usize {
129 self.header().cap
130 }
131
132 #[must_use]
134 pub fn as_slice(&self) -> &[Value] {
135 unsafe { core::slice::from_raw_parts(self.items_ptr(), self.len()) }
136 }
137
138 pub fn as_mut_slice(&mut self) -> &mut [Value] {
140 unsafe { core::slice::from_raw_parts_mut(self.items_ptr_mut(), self.len()) }
141 }
142
143 #[cfg(feature = "alloc")]
145 pub fn reserve(&mut self, additional: usize) {
146 let current_cap = self.capacity();
147 let desired_cap = self
148 .len()
149 .checked_add(additional)
150 .expect("capacity overflow");
151
152 if current_cap >= desired_cap {
153 return;
154 }
155
156 let new_cap = cmp::max(current_cap * 2, desired_cap.max(4));
157
158 unsafe {
159 let new_ptr = Self::realloc_ptr(self.0.heap_ptr_mut().cast(), new_cap);
160 self.0.set_ptr(new_ptr.cast());
161 }
162 }
163
164 #[cfg(feature = "alloc")]
166 pub fn push(&mut self, value: impl Into<Value>) {
167 self.reserve(1);
168 unsafe {
169 let len = self.header().len;
170 let ptr = self.items_ptr_mut().add(len);
171 ptr.write(value.into());
172 self.header_mut().len = len + 1;
173 }
174 }
175
176 pub fn pop(&mut self) -> Option<Value> {
178 let len = self.len();
179 if len == 0 {
180 return None;
181 }
182 unsafe {
183 self.header_mut().len = len - 1;
184 let ptr = self.items_ptr_mut().add(len - 1);
185 Some(ptr.read())
186 }
187 }
188
189 #[cfg(feature = "alloc")]
191 pub fn insert(&mut self, index: usize, value: impl Into<Value>) {
192 let len = self.len();
193 assert!(index <= len, "index out of bounds");
194
195 self.reserve(1);
196
197 unsafe {
198 let ptr = self.items_ptr_mut().add(index);
199 if index < len {
201 ptr::copy(ptr, ptr.add(1), len - index);
202 }
203 ptr.write(value.into());
204 self.header_mut().len = len + 1;
205 }
206 }
207
208 pub fn remove(&mut self, index: usize) -> Option<Value> {
210 let len = self.len();
211 if index >= len {
212 return None;
213 }
214
215 unsafe {
216 let ptr = self.items_ptr_mut().add(index);
217 let value = ptr.read();
218 if index < len - 1 {
220 ptr::copy(ptr.add(1), ptr, len - index - 1);
221 }
222 self.header_mut().len = len - 1;
223 Some(value)
224 }
225 }
226
227 pub fn swap_remove(&mut self, index: usize) -> Option<Value> {
230 let len = self.len();
231 if index >= len {
232 return None;
233 }
234
235 self.as_mut_slice().swap(index, len - 1);
236 self.pop()
237 }
238
239 pub fn clear(&mut self) {
241 while self.pop().is_some() {}
242 }
243
244 pub fn truncate(&mut self, len: usize) {
246 while self.len() > len {
247 self.pop();
248 }
249 }
250
251 #[must_use]
253 pub fn get(&self, index: usize) -> Option<&Value> {
254 self.as_slice().get(index)
255 }
256
257 pub fn get_mut(&mut self, index: usize) -> Option<&mut Value> {
259 self.as_mut_slice().get_mut(index)
260 }
261
262 #[cfg(feature = "alloc")]
264 pub fn shrink_to_fit(&mut self) {
265 let len = self.len();
266 let cap = self.capacity();
267
268 if len < cap {
269 unsafe {
270 let new_ptr = Self::realloc_ptr(self.0.heap_ptr_mut().cast(), len);
271 self.0.set_ptr(new_ptr.cast());
272 }
273 }
274 }
275
276 pub(crate) fn clone_impl(&self) -> Value {
277 let mut new = VArray::with_capacity(self.len());
278 for v in self.as_slice() {
279 new.push(v.clone());
280 }
281 new.0
282 }
283
284 pub(crate) fn drop_impl(&mut self) {
285 self.clear();
286 unsafe {
287 Self::dealloc_ptr(self.0.heap_ptr_mut().cast());
288 }
289 }
290}
291
292pub struct ArrayIntoIter {
296 array: VArray,
297}
298
299impl Iterator for ArrayIntoIter {
300 type Item = Value;
301
302 fn next(&mut self) -> Option<Self::Item> {
303 if self.array.is_empty() {
304 None
305 } else {
306 self.array.remove(0)
307 }
308 }
309
310 fn size_hint(&self) -> (usize, Option<usize>) {
311 let len = self.array.len();
312 (len, Some(len))
313 }
314}
315
316impl ExactSizeIterator for ArrayIntoIter {}
317
318impl IntoIterator for VArray {
319 type Item = Value;
320 type IntoIter = ArrayIntoIter;
321
322 fn into_iter(self) -> Self::IntoIter {
323 ArrayIntoIter { array: self }
324 }
325}
326
327impl<'a> IntoIterator for &'a VArray {
328 type Item = &'a Value;
329 type IntoIter = core::slice::Iter<'a, Value>;
330
331 fn into_iter(self) -> Self::IntoIter {
332 self.as_slice().iter()
333 }
334}
335
336impl<'a> IntoIterator for &'a mut VArray {
337 type Item = &'a mut Value;
338 type IntoIter = core::slice::IterMut<'a, Value>;
339
340 fn into_iter(self) -> Self::IntoIter {
341 self.as_mut_slice().iter_mut()
342 }
343}
344
345impl Deref for VArray {
348 type Target = [Value];
349
350 fn deref(&self) -> &[Value] {
351 self.as_slice()
352 }
353}
354
355impl DerefMut for VArray {
356 fn deref_mut(&mut self) -> &mut [Value] {
357 self.as_mut_slice()
358 }
359}
360
361impl Borrow<[Value]> for VArray {
362 fn borrow(&self) -> &[Value] {
363 self.as_slice()
364 }
365}
366
367impl BorrowMut<[Value]> for VArray {
368 fn borrow_mut(&mut self) -> &mut [Value] {
369 self.as_mut_slice()
370 }
371}
372
373impl AsRef<[Value]> for VArray {
374 fn as_ref(&self) -> &[Value] {
375 self.as_slice()
376 }
377}
378
379impl<I: SliceIndex<[Value]>> Index<I> for VArray {
382 type Output = I::Output;
383
384 fn index(&self, index: I) -> &Self::Output {
385 &self.as_slice()[index]
386 }
387}
388
389impl<I: SliceIndex<[Value]>> IndexMut<I> for VArray {
390 fn index_mut(&mut self, index: I) -> &mut Self::Output {
391 &mut self.as_mut_slice()[index]
392 }
393}
394
395impl PartialEq for VArray {
398 fn eq(&self, other: &Self) -> bool {
399 self.as_slice() == other.as_slice()
400 }
401}
402
403impl Eq for VArray {}
404
405impl PartialOrd for VArray {
406 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
407 let mut iter1 = self.iter();
409 let mut iter2 = other.iter();
410 loop {
411 match (iter1.next(), iter2.next()) {
412 (Some(a), Some(b)) => match a.partial_cmp(b) {
413 Some(Ordering::Equal) => continue,
414 other => return other,
415 },
416 (None, None) => return Some(Ordering::Equal),
417 (Some(_), None) => return Some(Ordering::Greater),
418 (None, Some(_)) => return Some(Ordering::Less),
419 }
420 }
421 }
422}
423
424impl Hash for VArray {
425 fn hash<H: Hasher>(&self, state: &mut H) {
426 self.as_slice().hash(state);
427 }
428}
429
430impl Debug for VArray {
431 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
432 Debug::fmt(self.as_slice(), f)
433 }
434}
435
436impl Default for VArray {
437 fn default() -> Self {
438 Self::new()
439 }
440}
441
442#[cfg(feature = "alloc")]
445impl<T: Into<Value>> FromIterator<T> for VArray {
446 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
447 let iter = iter.into_iter();
448 let (lower, _) = iter.size_hint();
449 let mut array = VArray::with_capacity(lower);
450 for v in iter {
451 array.push(v);
452 }
453 array
454 }
455}
456
457#[cfg(feature = "alloc")]
458impl<T: Into<Value>> Extend<T> for VArray {
459 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
460 let iter = iter.into_iter();
461 let (lower, _) = iter.size_hint();
462 self.reserve(lower);
463 for v in iter {
464 self.push(v);
465 }
466 }
467}
468
469#[cfg(feature = "alloc")]
472impl<T: Into<Value>> From<Vec<T>> for VArray {
473 fn from(vec: Vec<T>) -> Self {
474 vec.into_iter().collect()
475 }
476}
477
478#[cfg(feature = "alloc")]
479impl<T: Into<Value> + Clone> From<&[T]> for VArray {
480 fn from(slice: &[T]) -> Self {
481 slice.iter().cloned().collect()
482 }
483}
484
485impl AsRef<Value> for VArray {
488 fn as_ref(&self) -> &Value {
489 &self.0
490 }
491}
492
493impl AsMut<Value> for VArray {
494 fn as_mut(&mut self) -> &mut Value {
495 &mut self.0
496 }
497}
498
499impl From<VArray> for Value {
500 fn from(arr: VArray) -> Self {
501 arr.0
502 }
503}
504
505impl VArray {
506 #[inline]
508 pub fn into_value(self) -> Value {
509 self.0
510 }
511}
512
513#[cfg(test)]
514mod tests {
515 use super::*;
516 use crate::ValueType;
517
518 #[test]
519 fn test_new() {
520 let arr = VArray::new();
521 assert!(arr.is_empty());
522 assert_eq!(arr.len(), 0);
523 }
524
525 #[test]
526 fn test_push_pop() {
527 let mut arr = VArray::new();
528 arr.push(Value::from(1));
529 arr.push(Value::from(2));
530 arr.push(Value::from(3));
531
532 assert_eq!(arr.len(), 3);
533 assert_eq!(arr.pop().unwrap().as_number().unwrap().to_i64(), Some(3));
534 assert_eq!(arr.pop().unwrap().as_number().unwrap().to_i64(), Some(2));
535 assert_eq!(arr.pop().unwrap().as_number().unwrap().to_i64(), Some(1));
536 assert!(arr.pop().is_none());
537 }
538
539 #[test]
540 fn test_insert_remove() {
541 let mut arr = VArray::new();
542 arr.push(Value::from(1));
543 arr.push(Value::from(3));
544 arr.insert(1, Value::from(2));
545
546 assert_eq!(arr.len(), 3);
547 assert_eq!(arr[0].as_number().unwrap().to_i64(), Some(1));
548 assert_eq!(arr[1].as_number().unwrap().to_i64(), Some(2));
549 assert_eq!(arr[2].as_number().unwrap().to_i64(), Some(3));
550
551 let removed = arr.remove(1).unwrap();
552 assert_eq!(removed.as_number().unwrap().to_i64(), Some(2));
553 assert_eq!(arr.len(), 2);
554 }
555
556 #[test]
557 fn test_clone() {
558 let mut arr = VArray::new();
559 arr.push(Value::from("hello"));
560 arr.push(Value::from(42));
561
562 let arr2 = arr.clone();
563 assert_eq!(arr, arr2);
564 }
565
566 #[test]
567 fn inline_strings_in_array_remain_inline() {
568 let mut arr = VArray::new();
569 for len in 0..=crate::string::VString::INLINE_LEN_MAX.min(6) {
570 let s = "a".repeat(len);
571 arr.push(Value::from(s.as_str()));
572 }
573
574 for value in arr.iter() {
575 if value.value_type() == ValueType::String {
576 assert!(
577 value.is_inline_string(),
578 "array element lost inline representation"
579 );
580 }
581 }
582
583 let cloned = arr.clone();
584 for value in cloned.iter() {
585 if value.value_type() == ValueType::String {
586 assert!(
587 value.is_inline_string(),
588 "clone should preserve inline storage"
589 );
590 }
591 }
592 }
593
594 #[test]
595 fn test_iter() {
596 let mut arr = VArray::new();
597 arr.push(Value::from(1));
598 arr.push(Value::from(2));
599
600 let sum: i64 = arr
601 .iter()
602 .map(|v| v.as_number().unwrap().to_i64().unwrap())
603 .sum();
604 assert_eq!(sum, 3);
605 }
606
607 #[test]
608 fn test_collect() {
609 let arr: VArray = vec![1i64, 2, 3].into_iter().map(Value::from).collect();
610 assert_eq!(arr.len(), 3);
611 }
612}