facet_value/
array.rs

1//! Array value type.
2
3#[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/// Header for heap-allocated arrays.
19#[repr(C, align(8))]
20struct ArrayHeader {
21    /// Number of elements
22    len: usize,
23    /// Capacity (number of elements that can be stored)
24    cap: usize,
25    // Array of Value follows immediately after
26}
27
28/// An array value.
29///
30/// `VArray` is a dynamic array of `Value`s, similar to `Vec<Value>`.
31/// The length and capacity are stored in a heap-allocated header.
32#[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        // Go through heap_ptr directly to avoid creating intermediate reference
88        // that would limit provenance to just the header
89        unsafe { (self.0.heap_ptr() as *const ArrayHeader).add(1).cast() }
90    }
91
92    fn items_ptr_mut(&mut self) -> *mut Value {
93        // Use heap_ptr_mut directly to preserve mutable provenance
94        unsafe { (self.0.heap_ptr_mut() as *mut ArrayHeader).add(1).cast() }
95    }
96
97    /// Creates a new empty array.
98    #[cfg(feature = "alloc")]
99    #[must_use]
100    pub fn new() -> Self {
101        Self::with_capacity(0)
102    }
103
104    /// Creates a new array with the specified capacity.
105    #[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    /// Returns the number of elements.
115    #[must_use]
116    pub fn len(&self) -> usize {
117        self.header().len
118    }
119
120    /// Returns `true` if the array is empty.
121    #[must_use]
122    pub fn is_empty(&self) -> bool {
123        self.len() == 0
124    }
125
126    /// Returns the capacity.
127    #[must_use]
128    pub fn capacity(&self) -> usize {
129        self.header().cap
130    }
131
132    /// Returns a slice of the elements.
133    #[must_use]
134    pub fn as_slice(&self) -> &[Value] {
135        unsafe { core::slice::from_raw_parts(self.items_ptr(), self.len()) }
136    }
137
138    /// Returns a mutable slice of the elements.
139    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    /// Reserves capacity for at least `additional` more elements.
144    #[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    /// Pushes an element onto the back.
165    #[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    /// Pops an element from the back.
177    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    /// Inserts an element at the specified index.
190    #[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            // Shift elements to the right
200            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    /// Removes and returns the element at the specified index.
209    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            // Shift elements to the left
219            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    /// Removes an element by swapping it with the last element.
228    /// More efficient than `remove` but doesn't preserve order.
229    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    /// Clears the array.
240    pub fn clear(&mut self) {
241        while self.pop().is_some() {}
242    }
243
244    /// Truncates the array to the specified length.
245    pub fn truncate(&mut self, len: usize) {
246        while self.len() > len {
247            self.pop();
248        }
249    }
250
251    /// Gets an element by index.
252    #[must_use]
253    pub fn get(&self, index: usize) -> Option<&Value> {
254        self.as_slice().get(index)
255    }
256
257    /// Gets a mutable element by index.
258    pub fn get_mut(&mut self, index: usize) -> Option<&mut Value> {
259        self.as_mut_slice().get_mut(index)
260    }
261
262    /// Shrinks the capacity to match the length.
263    #[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
292// === Iterator ===
293
294/// Iterator over owned `Value`s from a `VArray`.
295pub 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
345// === Deref ===
346
347impl 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
379// === Index ===
380
381impl<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
395// === Comparison ===
396
397impl 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        // Element-wise comparison
408        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// === FromIterator / Extend ===
443
444#[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// === From implementations ===
470
471#[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
485// === Value conversions ===
486
487impl 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    /// Converts this VArray into a Value, consuming self.
507    #[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}