qudit_core/utils/
compact.rs

1use super::LimitedSizeVec;
2use super::storage::CompactStorage;
3use std::any::TypeId;
4use std::hash::Hash;
5
6const INLINE_CAPACITY: usize = 7;
7
8/// A space-efficient vector that stores small collections inline and transitions to heap allocation when needed.
9///
10/// `CompactVec` optimizes memory usage by storing up to INLINE_CAPACITY elements directly inline without heap allocation,
11/// automatically transitioning to heap storage when the capacity is exceeded or when inline storage
12/// cannot represent certain values.
13///
14/// # Examples
15///
16/// ```
17/// # use qudit_core::CompactVec;
18/// let mut vec: CompactVec<i8> = CompactVec::new();
19/// vec.push(1);
20/// vec.push(2);
21/// vec.push(3);
22/// assert_eq!(vec.len(), 3);
23/// assert!(vec.is_inline());
24/// ```
25#[derive(Debug, Clone)]
26pub enum CompactVec<T: CompactStorage> {
27    /// Inline storage for up to INLINE_CAPACITY elements.
28    Inline([T::InlineType; INLINE_CAPACITY], u8),
29
30    /// Heap storage for more than INLINE_CAPACITY elements.
31    Heap(LimitedSizeVec<T>),
32}
33
34impl<T: CompactStorage> CompactVec<T> {
35    /// Creates a new empty `CompactVec` using inline storage.
36    ///
37    /// The vector starts with inline storage and can hold up to INLINE_CAPACITY elements
38    /// before transitioning to heap allocation.
39    ///
40    /// # Examples
41    ///
42    /// ```
43    /// # use qudit_core::CompactVec;
44    /// let vec: CompactVec<i8> = CompactVec::new();
45    /// assert_eq!(vec.len(), 0);
46    /// assert!(vec.is_inline());
47    /// ```
48    #[inline]
49    pub fn new() -> Self {
50        CompactVec::Inline([T::InlineType::default(); INLINE_CAPACITY], 0)
51    }
52
53    /// Transitions the vector from inline storage to heap storage.
54    ///
55    /// This method converts all inline-stored elements to their full representation
56    /// and moves them to a heap-allocated vector. It's called automatically when
57    /// inline storage is insufficient (either due to capacity or representation limits).
58    ///
59    /// Returns a mutable reference to the heap vector for immediate use.
60    #[inline]
61    fn transition_to_heap(&mut self) -> &mut LimitedSizeVec<T> {
62        match self {
63            CompactVec::Inline(storage, length) => {
64                let mut heap_vec = LimitedSizeVec::new();
65                for i in 0..*length {
66                    heap_vec.push(T::from_inline(storage[i as usize]));
67                }
68                *self = CompactVec::Heap(heap_vec);
69                match self {
70                    CompactVec::Heap(vec) => vec,
71                    _ => unreachable!(),
72                }
73            }
74            CompactVec::Heap(vec) => vec,
75        }
76    }
77
78    /// Fast push for types where conversion is infallible (i8, u8)
79    /// Appends an element to the back of the collection without checking conversion validity.
80    ///
81    /// This method provides optimal performance for types with infallible inline conversions
82    /// (such as `i8` and `u8`) by skipping runtime conversion checks.
83    ///
84    /// # Safety
85    ///
86    /// This method should only be used with types where `T::CONVERSION_INFALLIBLE` is true.
87    /// Using it with other types may cause debug assertions to fail.
88    ///
89    /// # Examples
90    ///
91    /// ```
92    /// # use qudit_core::CompactVec;
93    /// let mut vec: CompactVec<i8> = CompactVec::new();
94    /// vec.push_unchecked(42);
95    /// vec.push_unchecked(-10);
96    /// assert_eq!(vec.len(), 2);
97    /// ```
98    #[inline]
99    pub fn push_unchecked(&mut self, value: T) {
100        debug_assert!(
101            T::CONVERSION_INFALLIBLE,
102            "push_unchecked only valid for infallible types"
103        );
104
105        match self {
106            CompactVec::Inline(storage, length) => {
107                if (*length as usize) < INLINE_CAPACITY {
108                    storage[*length as usize] = T::to_inline_unchecked(value);
109                    *length += 1;
110                } else {
111                    self.transition_to_heap().push(value);
112                }
113            }
114            CompactVec::Heap(vec) => {
115                vec.push(value);
116            }
117        }
118    }
119
120    /// Appends an element to the back of the collection.
121    ///
122    /// If the vector is using inline storage and has capacity, the element is stored inline.
123    /// If inline storage cannot represent the value or is full, the vector transitions to heap storage.
124    ///
125    /// # Examples
126    ///
127    /// ```
128    /// # use qudit_core::CompactVec;
129    /// let mut vec: CompactVec<i8> = CompactVec::new();
130    /// vec.push(1);
131    /// vec.push(2);
132    /// assert_eq!(vec.len(), 2);
133    /// ```
134    #[inline]
135    pub fn push(&mut self, value: T) {
136        // Fast path for infallible conversions
137        if T::CONVERSION_INFALLIBLE {
138            self.push_unchecked(value);
139            return;
140        }
141
142        match self {
143            CompactVec::Inline(storage, length) => {
144                if (*length as usize) < INLINE_CAPACITY {
145                    match T::to_inline(value) {
146                        Ok(inline_value) => {
147                            storage[*length as usize] = inline_value;
148                            *length += 1;
149                        }
150                        Err(original_value) => {
151                            self.transition_to_heap().push(original_value);
152                        }
153                    }
154                } else {
155                    self.transition_to_heap().push(value);
156                }
157            }
158            CompactVec::Heap(vec) => {
159                vec.push(value);
160            }
161        }
162    }
163
164    /// Removes the last element from the vector and returns it, or `None` if empty.
165    ///
166    /// # Examples
167    ///
168    /// ```
169    /// # use qudit_core::CompactVec;
170    /// let mut vec: CompactVec<i8> = CompactVec::new();
171    /// vec.push(1);
172    /// vec.push(2);
173    /// assert_eq!(vec.pop(), Some(2));
174    /// assert_eq!(vec.pop(), Some(1));
175    /// assert_eq!(vec.pop(), None);
176    /// ```
177    #[inline]
178    pub fn pop(&mut self) -> Option<T> {
179        match self {
180            CompactVec::Inline(storage, length) => {
181                if *length > 0 {
182                    *length -= 1;
183                    Some(T::from_inline(storage[*length as usize]))
184                } else {
185                    None
186                }
187            }
188            CompactVec::Heap(vec) => vec.pop(),
189        }
190    }
191
192    /// Returns the number of elements in the vector.
193    ///
194    /// # Examples
195    ///
196    /// ```
197    /// # use qudit_core::CompactVec;
198    /// let mut vec: CompactVec<i8> = CompactVec::new();
199    /// assert_eq!(vec.len(), 0);
200    /// vec.push(1);
201    /// assert_eq!(vec.len(), 1);
202    /// ```
203    #[inline]
204    pub fn len(&self) -> usize {
205        match self {
206            CompactVec::Inline(_, length) => *length as usize,
207            CompactVec::Heap(vec) => vec.len(),
208        }
209    }
210
211    /// Returns `true` if the vector contains no elements.
212    ///
213    /// # Examples
214    ///
215    /// ```
216    /// # use qudit_core::CompactVec;
217    /// let mut vec: CompactVec<i8> = CompactVec::new();
218    /// assert!(vec.is_empty());
219    /// vec.push(1);
220    /// assert!(!vec.is_empty());
221    /// ```
222    #[inline]
223    pub fn is_empty(&self) -> bool {
224        self.len() == 0
225    }
226
227    /// Returns a copy of the element at the given index, or `None` if the index is out of bounds.
228    ///
229    /// # Examples
230    ///
231    /// ```
232    /// # use qudit_core::CompactVec;
233    /// let mut vec: CompactVec<i8> = CompactVec::new();
234    /// vec.push(10);
235    /// vec.push(20);
236    /// assert_eq!(vec.get(0), Some(10));
237    /// assert_eq!(vec.get(1), Some(20));
238    /// assert_eq!(vec.get(2), None);
239    /// ```
240    #[inline]
241    pub fn get(&self, index: usize) -> Option<T> {
242        match self {
243            CompactVec::Inline(storage, length) => {
244                if index < *length as usize {
245                    Some(T::from_inline(storage[index]))
246                } else {
247                    None
248                }
249            }
250            CompactVec::Heap(vec) => vec.get(index).copied(),
251        }
252    }
253
254    /// Returns a copy of the element at the given index without bounds checking.
255    ///
256    /// This provides optimal performance when the caller can guarantee the index is valid.
257    ///
258    /// # Safety
259    ///
260    /// Calling this method with an out-of-bounds index is undefined behavior,
261    /// even with a safe type `T`.
262    ///
263    /// # Examples
264    ///
265    /// ```
266    /// # use qudit_core::CompactVec;
267    /// let mut vec: CompactVec<i8> = CompactVec::new();
268    /// vec.push(42);
269    /// unsafe {
270    ///     assert_eq!(vec.get_unchecked(0), 42);
271    /// }
272    /// ```
273    #[inline]
274    pub unsafe fn get_unchecked(&self, index: usize) -> T {
275        unsafe {
276            match self {
277                CompactVec::Inline(storage, _) => T::from_inline(*storage.get_unchecked(index)),
278                CompactVec::Heap(vec) => *vec.get_unchecked(index),
279            }
280        }
281    }
282
283    /// Returns `true` if the vector is currently using inline storage.
284    ///
285    /// This can be useful for performance-sensitive code that needs to know
286    /// whether operations will involve heap allocation or inline array access.
287    ///
288    /// # Examples
289    ///
290    /// ```
291    /// # use qudit_core::CompactVec;
292    /// let mut vec: CompactVec<i8> = CompactVec::new();
293    /// assert!(vec.is_inline());
294    ///
295    /// // Still inline after adding elements
296    /// for i in 0..7 {
297    ///     vec.push(i);
298    /// }
299    /// assert!(vec.is_inline());
300    ///
301    /// // Transitions to heap when capacity is exceeded
302    /// vec.push(7);
303    /// assert!(!vec.is_inline());
304    /// ```
305    #[inline]
306    pub fn is_inline(&self) -> bool {
307        matches!(self, CompactVec::Inline(_, _))
308    }
309
310    /// Returns the total capacity of the vector.
311    ///
312    /// For inline storage, this is always INLINE_CAPACITY. For heap storage, this returns
313    /// the current heap capacity which may be larger than the length.
314    ///
315    /// # Examples
316    ///
317    /// ```
318    /// # use qudit_core::CompactVec;
319    /// let vec: CompactVec<i8> = CompactVec::new();
320    /// assert_eq!(vec.capacity(), 7);
321    ///
322    /// let mut vec: CompactVec<i8> = CompactVec::new();
323    /// for i in 0..8 {  // Force transition to heap
324    ///     vec.push(i);
325    /// }
326    /// assert!(vec.capacity() >= 8);  // Heap capacity may be larger
327    /// ```
328    #[inline]
329    pub fn capacity(&self) -> usize {
330        match self {
331            CompactVec::Inline(_, _) => INLINE_CAPACITY,
332            CompactVec::Heap(vec) => vec.capacity(),
333        }
334    }
335
336    /// Returns the vector's contents as a slice.
337    ///
338    /// This method provides zero-cost slice access for types where `T` and `T::InlineType`
339    /// are the same (such as `i8` and `u8`). For other types, it panics since the
340    /// inline storage cannot be directly interpreted as a slice of `T`.
341    ///
342    /// # Panics
343    ///
344    /// Panics if `T` and `T::InlineType` are different types, as conversion would be required.
345    /// Use `iter()` instead for such types.
346    ///
347    /// # Examples
348    ///
349    /// ```
350    /// # use qudit_core::CompactVec;
351    /// let mut vec: CompactVec<i8> = CompactVec::new();
352    /// vec.push(1);
353    /// vec.push(2);
354    /// vec.push(3);
355    /// let slice = vec.as_slice();
356    /// assert_eq!(slice, &[1, 2, 3]);
357    /// ```
358    #[inline]
359    pub fn as_slice(&self) -> &[T] {
360        // Check if T and T::InlineType are the same type (zero-cost conversion)
361        if TypeId::of::<T>() == TypeId::of::<T::InlineType>() {
362            match self {
363                CompactVec::Inline(storage, length) => {
364                    unsafe {
365                        // Safe because T == T::InlineType
366                        let ptr = storage.as_ptr() as *const T;
367                        std::slice::from_raw_parts(ptr, *length as usize)
368                    }
369                }
370                CompactVec::Heap(vec) => vec.as_slice(),
371            }
372        } else {
373            // TODO: transition to HEAP, then return slice
374            panic!(
375                "Cannot get slice from inline storage for non-zero-cost types - use iter() instead"
376            )
377        }
378    }
379
380    /// Removes and returns the element at position `index`, shifting all elements after it to the left.
381    ///
382    /// # Panics
383    /// Panics if `index` is out of bounds.
384    #[inline]
385    pub fn remove(&mut self, index: usize) -> T {
386        if index >= self.len() {
387            panic!(
388                "removal index (is {}) should be < len (is {})",
389                index,
390                self.len()
391            );
392        }
393
394        match self {
395            CompactVec::Inline(storage, length) => {
396                let result = T::from_inline(storage[index]);
397                // Shift elements left
398                for i in index..(*length as usize - 1) {
399                    storage[i] = storage[i + 1];
400                }
401                *length -= 1;
402                result
403            }
404            CompactVec::Heap(vec) => vec.remove(index),
405        }
406    }
407
408    /// Inserts an element at position `index`, shifting all elements after it to the right.
409    ///
410    /// # Panics
411    /// Panics if `index > len`.
412    #[inline]
413    pub fn insert(&mut self, index: usize, element: T) {
414        if index > self.len() {
415            panic!(
416                "insertion index (is {}) should be <= len (is {})",
417                index,
418                self.len()
419            );
420        }
421
422        match self {
423            CompactVec::Inline(storage, length) => {
424                if (*length as usize) >= INLINE_CAPACITY || T::to_inline(element).is_err() {
425                    self.transition_to_heap().insert(index, element);
426                } else {
427                    // Shift elements right
428                    for i in (index..*length as usize).rev() {
429                        storage[i + 1] = storage[i];
430                    }
431                    storage[index] = T::to_inline(element).unwrap_or_else(|_| unreachable!());
432                    *length += 1;
433                }
434            }
435            CompactVec::Heap(vec) => vec.insert(index, element),
436        }
437    }
438
439    /// Shortens the vector, keeping the first `len` elements and dropping the rest.
440    ///
441    /// If `len` is greater than the vector's current length, this has no effect.
442    #[inline]
443    pub fn truncate(&mut self, len: usize) {
444        match self {
445            CompactVec::Inline(_, length) => {
446                if len < *length as usize {
447                    *length = len as u8;
448                }
449            }
450            CompactVec::Heap(vec) => vec.truncate(len),
451        }
452    }
453
454    /// Resizes the vector to the given length.
455    ///
456    /// If `new_len` is greater than `len`, the vector is extended with clones of `value`.
457    /// If `new_len` is less than `len`, the vector is truncated.
458    #[inline]
459    pub fn resize(&mut self, new_len: usize, value: T) {
460        let current_len = self.len();
461        if new_len > current_len {
462            for _ in current_len..new_len {
463                self.push(value);
464            }
465        } else {
466            self.truncate(new_len);
467        }
468    }
469
470    /// Extends the vector by cloning elements from a slice.
471    ///
472    /// All elements from the slice are appended to the vector in order.
473    /// If the vector is using inline storage and the additional elements
474    /// cause it to exceed capacity or cannot be represented inline,
475    /// it will transition to heap storage automatically.
476    ///
477    /// # Examples
478    ///
479    /// ```
480    /// # use qudit_core::CompactVec;
481    /// let mut vec: CompactVec<i8> = CompactVec::new();
482    /// vec.extend_from_slice(&[1, 2, 3]);
483    /// assert_eq!(vec.len(), 3);
484    ///
485    /// vec.extend_from_slice(&[4, 5]);
486    /// assert_eq!(vec.len(), 5);
487    /// ```
488    #[inline]
489    pub fn extend_from_slice(&mut self, other: &[T]) {
490        for item in other {
491            self.push(*item);
492        }
493    }
494
495    /// Reserves capacity for at least `additional` more elements.
496    ///
497    /// For inline storage, this will transition to heap if the requested
498    /// additional capacity would exceed the inline capacity of INLINE_CAPACITY elements.
499    /// For heap storage, this forwards the call to the underlying vector's
500    /// reserve method.
501    ///
502    /// # Examples
503    ///
504    /// ```
505    /// # use qudit_core::CompactVec;
506    /// let mut vec: CompactVec<i8> = CompactVec::new();
507    /// vec.reserve(10);  // This will transition to heap since 10 > INLINE_CAPACITY
508    /// assert!(!vec.is_inline());
509    /// assert!(vec.capacity() >= 10);
510    /// ```
511    #[inline]
512    pub fn reserve(&mut self, additional: usize) {
513        match self {
514            CompactVec::Inline(_, _) => {
515                let new_capacity = self.len() + additional;
516
517                if self.capacity() >= new_capacity {
518                    return;
519                }
520
521                if new_capacity > INLINE_CAPACITY {
522                    self.transition_to_heap().reserve(additional);
523                }
524            }
525            CompactVec::Heap(vec) => vec.reserve(additional),
526        }
527    }
528
529    /// Clears the vector, removing all elements but keeping allocated capacity.
530    ///
531    /// For inline storage, this resets the length to 0 without changing the storage mode.
532    /// For heap storage, this forwards the call to the underlying vector, which clears
533    /// all elements but preserves the allocated heap capacity.
534    ///
535    /// # Examples
536    ///
537    /// ```
538    /// # use qudit_core::CompactVec;
539    /// let mut vec: CompactVec<i8> = CompactVec::new();
540    /// vec.push(1);
541    /// vec.push(2);
542    /// vec.push(3);
543    /// assert_eq!(vec.len(), 3);
544    ///
545    /// vec.clear();
546    /// assert_eq!(vec.len(), 0);
547    /// assert!(vec.is_empty());
548    /// ```
549    #[inline]
550    pub fn clear(&mut self) {
551        match self {
552            CompactVec::Inline(_, length) => *length = 0,
553            CompactVec::Heap(vec) => vec.clear(),
554        }
555    }
556
557    /// Returns `true` if the vector contains an element equal to `value`.
558    ///
559    /// # Examples
560    ///
561    /// ```
562    /// # use qudit_core::CompactVec;
563    /// let mut vec: CompactVec<i8> = CompactVec::new();
564    /// vec.push(1);
565    /// vec.push(2);
566    /// vec.push(3);
567    ///
568    /// assert!(vec.contains(&1));
569    /// assert!(!vec.contains(&4));
570    /// ```
571    #[inline]
572    pub fn contains(&self, value: &T) -> bool
573    where
574        T: PartialEq,
575    {
576        match self {
577            CompactVec::Inline(storage, length) => {
578                for i in 0..*length as usize {
579                    if T::from_inline(storage[i]) == *value {
580                        return true;
581                    }
582                }
583                false
584            }
585            CompactVec::Heap(vec) => vec.contains(value),
586        }
587    }
588
589    /// Sorts the vector in-place using the natural ordering of elements.
590    ///
591    /// This uses insertion sort for inline storage (which is efficient for small arrays)
592    /// and delegates to the underlying vector's sort method for heap storage.
593    ///
594    /// # Examples
595    ///
596    /// ```
597    /// # use qudit_core::CompactVec;
598    /// let mut vec: CompactVec<i8> = CompactVec::new();
599    /// vec.extend_from_slice(&[3, 1, 4, 1, 5]);
600    /// vec.sort();
601    /// assert_eq!(vec.as_slice(), &[1, 1, 3, 4, 5]);
602    /// ```
603    #[inline]
604    pub fn sort(&mut self)
605    where
606        T: Ord,
607    {
608        match self {
609            CompactVec::Inline(storage, length) => {
610                if *length <= 1 {
611                    return;
612                }
613
614                for i in 1..*length {
615                    let mut j = i as usize;
616                    while j > 0 && T::from_inline(storage[j - 1]) > T::from_inline(storage[j]) {
617                        storage.swap(j - 1, j);
618                        j -= 1;
619                    }
620                }
621            }
622            CompactVec::Heap(vec) => vec.sort(),
623        }
624    }
625
626    /// Takes ownership of the vector's contents, leaving the original empty.
627    ///
628    /// This is equivalent to `std::mem::replace(self, CompactVec::new())` but more explicit.
629    /// The original vector is left in a new, empty state (using inline storage).
630    ///
631    /// # Examples
632    ///
633    /// ```
634    /// # use qudit_core::CompactVec;
635    /// let mut vec: CompactVec<i8> = CompactVec::new();
636    /// vec.extend_from_slice(&[1, 2, 3]);
637    ///
638    /// let taken = vec.take();
639    /// assert_eq!(taken.len(), 3);
640    /// assert_eq!(vec.len(), 0);
641    /// assert!(vec.is_empty());
642    /// ```
643    #[inline]
644    pub fn take(&mut self) -> Self {
645        std::mem::take(self)
646    }
647
648    /// Returns a mutable reference to the element at the given index, or `None` if out of bounds.
649    ///
650    /// For inline storage with non-zero-cost type conversions, this method will transition
651    /// the vector to heap storage to provide mutable access. For zero-cost conversions
652    /// (where `T` and `T::InlineType` are the same), it provides direct mutable access
653    /// to the inline storage.
654    ///
655    /// # Examples
656    ///
657    /// ```
658    /// # use qudit_core::CompactVec;
659    /// let mut vec: CompactVec<i8> = CompactVec::new();
660    /// vec.push(10);
661    /// vec.push(20);
662    ///
663    /// if let Some(elem) = vec.get_mut(1) {
664    ///     *elem = 25;
665    /// }
666    /// assert_eq!(vec.get(1), Some(25));
667    /// ```
668    #[inline]
669    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
670        // Check if T and T::InlineType are the same type (zero-cost conversion)
671        match self {
672            CompactVec::Inline(storage, length) => {
673                if index < *length as usize {
674                    if TypeId::of::<T>() == TypeId::of::<T::InlineType>() {
675                        unsafe {
676                            // Safe because T == T::InlineType
677                            let ptr = storage.as_mut_ptr() as *mut T;
678                            Some(&mut *ptr.add(index))
679                        }
680                    } else {
681                        // We need to transition to heap for mutable access
682                        self.transition_to_heap().get_mut(index)
683                    }
684                } else {
685                    None
686                }
687            }
688            CompactVec::Heap(vec) => vec.get_mut(index),
689        }
690    }
691
692    /// Returns a mutable reference to an element without bounds checking.
693    ///
694    /// For inline storage with non-zero-cost type conversions, this method will transition
695    /// the vector to heap storage to provide mutable access. For zero-cost conversions,
696    /// it provides direct unsafe mutable access to the inline storage.
697    ///
698    /// # Safety
699    ///
700    /// Calling this method with an out-of-bounds index is undefined behavior,
701    /// even with a safe type `T`.
702    ///
703    /// # Examples
704    ///
705    /// ```
706    /// # use qudit_core::CompactVec;
707    /// let mut vec: CompactVec<i8> = CompactVec::new();
708    /// vec.push(42);
709    /// unsafe {
710    ///     *vec.get_mut_unchecked(0) = 100;
711    ///     assert_eq!(vec.get(0), Some(100));
712    /// }
713    /// ```
714    #[inline]
715    pub unsafe fn get_mut_unchecked(&mut self, index: usize) -> &mut T {
716        unsafe {
717            // Check if T and T::InlineType are the same type (zero-cost conversion)
718            match self {
719                CompactVec::Inline(storage, _) => {
720                    if TypeId::of::<T>() == TypeId::of::<T::InlineType>() {
721                        // Safe because T == T::InlineType and caller guarantees bounds
722                        let ptr = storage.as_mut_ptr() as *mut T;
723                        &mut *ptr.add(index)
724                    } else {
725                        self.transition_to_heap().get_mut_unchecked(index)
726                    }
727                }
728                CompactVec::Heap(vec) => vec.get_mut_unchecked(index),
729            }
730        }
731    }
732
733    /// Returns the vector's contents as a mutable slice.
734    ///
735    /// For inline storage with non-zero-cost type conversions, this method will transition
736    /// the vector to heap storage to provide mutable slice access. For zero-cost conversions
737    /// (where `T` and `T::InlineType` are the same), it provides direct mutable access
738    /// to the inline storage as a slice.
739    ///
740    /// # Examples
741    ///
742    /// ```
743    /// # use qudit_core::CompactVec;
744    /// let mut vec: CompactVec<i8> = CompactVec::new();
745    /// vec.extend_from_slice(&[1, 2, 3]);
746    ///
747    /// let slice = vec.as_slice_mut();
748    /// slice[1] = 10;
749    /// assert_eq!(vec.get(1), Some(10));
750    /// ```
751    #[inline]
752    pub fn as_slice_mut(&mut self) -> &mut [T] {
753        // Check if T and T::InlineType are the same type (zero-cost conversion)
754        match self {
755            CompactVec::Inline(storage, length) => {
756                if TypeId::of::<T>() == TypeId::of::<T::InlineType>() {
757                    unsafe {
758                        // Safe because T == T::InlineType
759                        let ptr = storage.as_mut_ptr() as *mut T;
760                        std::slice::from_raw_parts_mut(ptr, *length as usize)
761                    }
762                } else {
763                    self.transition_to_heap().as_mut()
764                }
765            }
766            CompactVec::Heap(vec) => vec.as_mut(),
767        }
768    }
769
770    /// Returns an iterator over the vector's elements.
771    ///
772    /// This iterator is optimized for inline storage, avoiding heap allocations
773    /// and providing efficient element access for small collections.
774    ///
775    /// # Examples
776    ///
777    /// ```
778    /// # use qudit_core::CompactVec;
779    /// let mut vec: CompactVec<i8> = CompactVec::new();
780    /// vec.extend_from_slice(&[1, 2, 3]);
781    ///
782    /// let sum: i8 = vec.iter().sum();
783    /// assert_eq!(sum, 6);
784    ///
785    /// for (i, value) in vec.iter().enumerate() {
786    ///     println!("Element {}: {}", i, value);
787    /// }
788    /// ```
789    #[inline]
790    pub fn iter(&self) -> CompactVecIter<'_, T> {
791        match self {
792            CompactVec::Inline(storage, length) => CompactVecIter::Inline(storage, 0, *length),
793            CompactVec::Heap(vec) => CompactVecIter::Heap(vec.iter()),
794        }
795    }
796}
797
798impl<T: CompactStorage> Default for CompactVec<T> {
799    /// Creates an empty `CompactVec<T>`.
800    ///
801    /// This is equivalent to `CompactVec::new()`.
802    #[inline]
803    fn default() -> Self {
804        Self::new()
805    }
806}
807
808/// An iterator over the elements of a `CompactVec`.
809///
810/// This iterator is optimized to handle both inline and heap storage modes efficiently.
811/// It's created by calling `iter()` on a `CompactVec`.
812#[derive(Debug, Clone)]
813pub enum CompactVecIter<'a, T: CompactStorage> {
814    /// Iterator over inline storage elements.
815    ///
816    /// Contains: (storage reference, current index, total length)
817    Inline(&'a [T::InlineType; INLINE_CAPACITY], u8, u8),
818    /// Iterator over heap storage elements.
819    Heap(std::slice::Iter<'a, T>),
820}
821
822impl<'a, T: CompactStorage> Iterator for CompactVecIter<'a, T> {
823    type Item = T;
824
825    #[inline]
826    fn next(&mut self) -> Option<Self::Item> {
827        match self {
828            CompactVecIter::Inline(storage, index, length) => {
829                if *index < *length {
830                    let result = T::from_inline(storage[*index as usize]);
831                    *index += 1;
832                    Some(result)
833                } else {
834                    None
835                }
836            }
837            CompactVecIter::Heap(iter) => iter.next().copied(),
838        }
839    }
840
841    #[inline]
842    fn size_hint(&self) -> (usize, Option<usize>) {
843        match self {
844            CompactVecIter::Inline(_, index, length) => {
845                let remaining = (*length - *index) as usize;
846                (remaining, Some(remaining))
847            }
848            CompactVecIter::Heap(iter) => iter.size_hint(),
849        }
850    }
851}
852
853impl<'a, T: CompactStorage> ExactSizeIterator for CompactVecIter<'a, T> {}
854
855impl<T> AsMut<[T]> for CompactVec<T>
856where
857    T: CompactStorage,
858{
859    /// Returns a mutable slice of the vector's contents.
860    ///
861    /// This delegates to `as_slice_mut()`.
862    #[inline]
863    fn as_mut(&mut self) -> &mut [T] {
864        self.as_slice_mut()
865    }
866}
867
868/// Enables converting a `Vec<T>` into a `CompactVec<T>`.
869impl<T> From<Vec<T>> for CompactVec<T>
870where
871    T: CompactStorage,
872{
873    /// Creates a `CompactVec` from a standard `Vec`.
874    ///
875    /// All elements are moved from the source vector. If the vector has INLINE_CAPACITY or fewer
876    /// elements and they can all be represented inline, the result will use inline storage.
877    /// Otherwise, it will use heap storage.
878    ///
879    /// # Examples
880    ///
881    /// ```
882    /// # use qudit_core::CompactVec;
883    /// let vec = vec![1i8, 2, 3];
884    /// let compact: CompactVec<i8> = vec.into();
885    /// assert_eq!(compact.len(), 3);
886    /// assert!(compact.is_inline());
887    /// ```
888    #[inline]
889    fn from(vec: Vec<T>) -> Self {
890        if vec.len() > INLINE_CAPACITY {
891            Self::Heap(LimitedSizeVec::from(vec))
892        } else {
893            let mut compact_vec = Self::new();
894            for item in vec {
895                compact_vec.push(item);
896            }
897            compact_vec
898        }
899    }
900}
901
902/// Enables converting a fixed-size array `[T; N]` into a `CompactVec<T>`.
903impl<T, const N: usize> From<[T; N]> for CompactVec<T>
904where
905    T: CompactStorage,
906{
907    /// Creates a `CompactVec` from a fixed-size array.
908    ///
909    /// # Examples
910    ///
911    /// ```
912    /// # use qudit_core::CompactVec;
913    /// let array = [1i8, 2, 3, 4, 5];
914    /// let compact: CompactVec<i8> = array.into();
915    /// assert_eq!(compact.len(), 5);
916    /// ```
917    #[inline]
918    fn from(array: [T; N]) -> Self {
919        let mut compact_vec = Self::new();
920        for item in array {
921            compact_vec.push(item);
922        }
923        compact_vec
924    }
925}
926
927/// Enables converting a fixed-size array `[T; N]` into a `CompactVec<T>`.
928impl<T, const N: usize> From<&[T; N]> for CompactVec<T>
929where
930    T: CompactStorage,
931{
932    /// Creates a `CompactVec` from a fixed-size array.
933    ///
934    /// # Examples
935    ///
936    /// ```
937    /// # use qudit_core::CompactVec;
938    /// let array = [1i8, 2, 3, 4, 5];
939    /// let compact: CompactVec<i8> = array.into();
940    /// assert_eq!(compact.len(), 5);
941    /// ```
942    #[inline]
943    fn from(array: &[T; N]) -> Self {
944        let mut compact_vec = Self::new();
945        for item in array {
946            compact_vec.push(*item);
947        }
948        compact_vec
949    }
950}
951
952/// Enables converting a slice `&[T]` into a `CompactVec<T>`.
953impl<T> From<&[T]> for CompactVec<T>
954where
955    T: CompactStorage + Clone,
956{
957    /// Creates a `CompactVec` from a slice by cloning all elements.
958    ///
959    /// # Examples
960    ///
961    /// ```
962    /// # use qudit_core::CompactVec;
963    /// let slice = &[1i8, 2, 3];
964    /// let compact: CompactVec<i8> = slice.into();
965    /// assert_eq!(compact.len(), 3);
966    /// ```
967    #[inline]
968    fn from(slice: &[T]) -> Self {
969        let mut compact_vec = Self::new();
970        for item in slice {
971            compact_vec.push(*item);
972        }
973        compact_vec
974    }
975}
976
977/// Enables converting a `&Vec<T>` into a `CompactVec<T>`.
978impl<T> From<&Vec<T>> for CompactVec<T>
979where
980    T: CompactStorage + Clone,
981{
982    /// Creates a `CompactVec` from a vector reference by cloning all elements.
983    ///
984    /// This delegates to the `&[T]` implementation.
985    #[inline]
986    fn from(vec: &Vec<T>) -> Self {
987        Self::from(vec.as_slice())
988    }
989}
990
991/// Enables converting a `CompactVec<T>` into a standard `Vec<T>`.
992impl<T> From<CompactVec<T>> for Vec<T>
993where
994    T: CompactStorage,
995{
996    /// Creates a standard `Vec` from a `CompactVec`.
997    ///
998    /// For inline storage, a new vector is allocated and all elements are copied.
999    /// For heap storage, the underlying vector is returned directly when possible.
1000    ///
1001    /// # Examples
1002    ///
1003    /// ```
1004    /// # use qudit_core::CompactVec;
1005    /// let mut compact: CompactVec<i8> = CompactVec::new();
1006    /// compact.extend_from_slice(&[1, 2, 3]);
1007    ///
1008    /// let vec: Vec<i8> = compact.into();
1009    /// assert_eq!(vec, vec![1, 2, 3]);
1010    /// ```
1011    #[inline]
1012    fn from(compact_vec: CompactVec<T>) -> Self {
1013        match compact_vec {
1014            CompactVec::Inline(storage, length) => {
1015                let mut vec = Vec::with_capacity(length as usize);
1016                for i in 0..length {
1017                    vec.push(T::from_inline(storage[i as usize]));
1018                }
1019                vec
1020            }
1021            CompactVec::Heap(vec) => vec.into(),
1022        }
1023    }
1024}
1025
1026impl<T: CompactStorage + Hash> Hash for CompactVec<T> {
1027    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1028        for item in self.iter() {
1029            item.hash(state);
1030        }
1031    }
1032}
1033
1034impl<T: CompactStorage + PartialEq> PartialEq for CompactVec<T> {
1035    fn eq(&self, other: &Self) -> bool {
1036        if self.len() != other.len() {
1037            return false;
1038        }
1039
1040        self.iter().zip(other.iter()).all(|(a, b)| a == b)
1041    }
1042}
1043
1044impl<T: CompactStorage + Eq> Eq for CompactVec<T> {}
1045
1046/// An owning iterator over the elements of a `CompactVec`.
1047///
1048/// This iterator moves elements out of the vector, consuming it in the process.
1049/// It's created by calling `into_iter()` on a `CompactVec` or by using a `for` loop.
1050/// Like `CompactVecIter`, it's optimized to handle both inline and heap storage modes.
1051pub enum CompactVecIntoIter<T: CompactStorage> {
1052    /// Iterator that moves out of inline storage elements.
1053    ///
1054    /// Contains: (storage array, current index, total length)
1055    Inline([T::InlineType; INLINE_CAPACITY], u8, u8),
1056    /// Iterator that moves out of heap storage elements.
1057    Heap(<LimitedSizeVec<T> as IntoIterator>::IntoIter),
1058}
1059
1060impl<T: CompactStorage> Iterator for CompactVecIntoIter<T> {
1061    type Item = T;
1062
1063    #[inline]
1064    fn next(&mut self) -> Option<Self::Item> {
1065        match self {
1066            CompactVecIntoIter::Inline(storage, index, length) => {
1067                if *index < *length {
1068                    let result = T::from_inline(storage[*index as usize]);
1069                    *index += 1;
1070                    Some(result)
1071                } else {
1072                    None
1073                }
1074            }
1075            CompactVecIntoIter::Heap(iter) => iter.next(),
1076        }
1077    }
1078
1079    #[inline]
1080    fn size_hint(&self) -> (usize, Option<usize>) {
1081        match self {
1082            CompactVecIntoIter::Inline(_, index, length) => {
1083                let remaining = (*length - *index) as usize;
1084                (remaining, Some(remaining))
1085            }
1086            CompactVecIntoIter::Heap(iter) => iter.size_hint(),
1087        }
1088    }
1089}
1090
1091impl<T: CompactStorage> ExactSizeIterator for CompactVecIntoIter<T> {}
1092
1093impl<T: CompactStorage> FromIterator<T> for CompactVec<T> {
1094    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1095        let iter = iter.into_iter();
1096        let (min_len, max_len) = iter.size_hint();
1097
1098        if let Some(len) = max_len {
1099            if len <= INLINE_CAPACITY {
1100                // If the known size fits within inline capacity:
1101                // For types with infallible inline conversions (e.g., i8, u8),
1102                // we can directly populate the inline array for maximum performance.
1103                if T::CONVERSION_INFALLIBLE {
1104                    let mut storage = [T::InlineType::default(); INLINE_CAPACITY];
1105                    let mut i = 0;
1106                    for next in iter {
1107                        storage[i] = T::to_inline_unchecked(next);
1108                        i += 1;
1109                    }
1110                    return CompactVec::Inline(storage, i as u8);
1111                }
1112                // For types with fallible inline conversions, even if the size fits,
1113                // we cannot pre-populate without checking each item. In this case,
1114                // we fall through to the general `push` loop, which handles conversions
1115                // and potential transitions to heap as needed.
1116            } else {
1117                // If the known size exceeds inline capacity, it will definitely be a heap-allocated vector.
1118                // We collect all elements directly into a LimitedSizeVec, leveraging its FromIterator
1119                // implementation which uses the size hint for efficient allocation.
1120                return CompactVec::Heap(iter.collect::<LimitedSizeVec<T>>());
1121            }
1122        } else {
1123            // If the exact size is unknown, but the lower bound suggests it's likely to be large,
1124            // we start with a heap-allocated vector to avoid multiple reallocations during inline-to-heap transition.
1125            if min_len > INLINE_CAPACITY {
1126                // Collect into a LimitedSizeVec. Its FromIterator will use min_len for initial capacity.
1127                return CompactVec::Heap(iter.collect::<LimitedSizeVec<T>>());
1128            }
1129        }
1130
1131        // Default path: This covers cases where a specialized path wasn't taken,
1132        let mut compact_vec = Self::new();
1133        for item in iter {
1134            compact_vec.push(item);
1135        }
1136        compact_vec
1137    }
1138}
1139
1140/// Enables using `CompactVec` as a mutable slice through the `AsMut` trait.
1141impl<T> IntoIterator for CompactVec<T>
1142where
1143    T: CompactStorage,
1144{
1145    type Item = T;
1146    type IntoIter = CompactVecIntoIter<T>;
1147
1148    /// Creates an owning iterator that consumes the vector.
1149    ///
1150    /// # Examples
1151    ///
1152    /// ```
1153    /// # use qudit_core::CompactVec;
1154    /// let mut vec: CompactVec<i8> = CompactVec::new();
1155    /// vec.extend_from_slice(&[1, 2, 3]);
1156    ///
1157    /// let doubled: Vec<i8> = vec.into_iter().map(|x| x * 2).collect();
1158    /// assert_eq!(doubled, vec![2, 4, 6]);
1159    /// ```
1160    #[inline]
1161    fn into_iter(self) -> Self::IntoIter {
1162        match self {
1163            CompactVec::Inline(storage, length) => CompactVecIntoIter::Inline(storage, 0, length),
1164            CompactVec::Heap(vec) => CompactVecIntoIter::Heap(vec.into_iter()),
1165        }
1166    }
1167}
1168
1169impl<'a, T> IntoIterator for &'a CompactVec<T>
1170where
1171    T: CompactStorage,
1172{
1173    type Item = T;
1174    type IntoIter = CompactVecIter<'a, T>;
1175
1176    /// Creates an iterator over references to the vector's elements.
1177    ///
1178    /// This delegates to `iter()`.
1179    #[inline]
1180    fn into_iter(self) -> Self::IntoIter {
1181        self.iter()
1182    }
1183}
1184
1185impl<'a, T> IntoIterator for &'a mut CompactVec<T>
1186where
1187    T: CompactStorage,
1188{
1189    type Item = &'a mut T;
1190    type IntoIter = std::slice::IterMut<'a, T>;
1191
1192    /// Creates an iterator over mutable references to the vector's elements.
1193    ///
1194    /// For inline storage with non-zero-cost conversions, this will transition
1195    /// the vector to heap storage.
1196    #[inline]
1197    fn into_iter(self) -> Self::IntoIter {
1198        self.as_slice_mut().iter_mut()
1199    }
1200}
1201
1202// Specialized implementations for zero-cost conversions (T == T::InlineType)
1203// These provide optimal performance for i8 and u8 types.
1204/// Enables treating `CompactVec<i8>` as a slice through the `Deref` trait.
1205///
1206/// This implementation is only available for `i8` because it has zero-cost
1207/// conversion with its inline type.
1208impl std::ops::Deref for CompactVec<i8> {
1209    type Target = [i8];
1210
1211    /// Returns a slice view of the vector's contents.
1212    ///
1213    /// This provides zero-cost access to the underlying storage.
1214    #[inline]
1215    fn deref(&self) -> &Self::Target {
1216        match self {
1217            CompactVec::Inline(storage, length) => unsafe {
1218                std::slice::from_raw_parts(storage.as_ptr(), *length as usize)
1219            },
1220            CompactVec::Heap(vec) => vec.as_slice(),
1221        }
1222    }
1223}
1224
1225/// Enables treating `CompactVec<u8>` as a slice through the `Deref` trait.
1226///
1227/// This implementation is only available for `u8` because it has zero-cost
1228/// conversion with its inline type.
1229impl std::ops::Deref for CompactVec<u8> {
1230    type Target = [u8];
1231
1232    /// Returns a slice view of the vector's contents.
1233    ///
1234    /// This provides zero-cost access to the underlying storage.
1235    #[inline]
1236    fn deref(&self) -> &Self::Target {
1237        match self {
1238            CompactVec::Inline(storage, length) => unsafe {
1239                std::slice::from_raw_parts(storage.as_ptr(), *length as usize)
1240            },
1241            CompactVec::Heap(vec) => vec.as_slice(),
1242        }
1243    }
1244}
1245
1246/// Enables indexing `CompactVec<i8>` with `[]` syntax.
1247impl std::ops::Index<usize> for CompactVec<i8> {
1248    type Output = i8;
1249
1250    /// Returns a reference to the element at the given index.
1251    ///
1252    /// # Panics
1253    ///
1254    /// Panics if the index is out of bounds.
1255    #[inline]
1256    fn index(&self, index: usize) -> &Self::Output {
1257        match self {
1258            CompactVec::Inline(storage, length) => {
1259                if index >= *length as usize {
1260                    panic!(
1261                        "index out of bounds: the len is {} but the index is {}",
1262                        *length, index
1263                    );
1264                }
1265                &storage[index]
1266            }
1267            CompactVec::Heap(vec) => &vec[index],
1268        }
1269    }
1270}
1271
1272/// Enables indexing `CompactVec<u8>` with `[]` syntax.
1273impl std::ops::Index<usize> for CompactVec<u8> {
1274    type Output = u8;
1275
1276    /// Returns a reference to the element at the given index.
1277    ///
1278    /// # Panics
1279    ///
1280    /// Panics if the index is out of bounds.
1281    #[inline]
1282    fn index(&self, index: usize) -> &Self::Output {
1283        match self {
1284            CompactVec::Inline(storage, length) => {
1285                if index >= *length as usize {
1286                    panic!(
1287                        "index out of bounds: the len is {} but the index is {}",
1288                        *length, index
1289                    );
1290                }
1291                &storage[index]
1292            }
1293            CompactVec::Heap(vec) => &vec[index],
1294        }
1295    }
1296}
1297
1298/// Enables using `CompactVec<i8>` where `&[i8]` is expected.
1299impl AsRef<[i8]> for CompactVec<i8> {
1300    /// Returns a slice view of the vector's contents.
1301    #[inline]
1302    fn as_ref(&self) -> &[i8] {
1303        self.as_slice()
1304    }
1305}
1306
1307/// Enables using `CompactVec<u8>` where `&[u8]` is expected.
1308impl AsRef<[u8]> for CompactVec<u8> {
1309    /// Returns a slice view of the vector's contents.
1310    #[inline]
1311    fn as_ref(&self) -> &[u8] {
1312        self.as_slice()
1313    }
1314}
1315
1316#[cfg(test)]
1317mod tests {
1318    use super::*;
1319
1320    // Helper function to create a test CompactVec with known elements
1321    fn test_vec_with_elements<T: CompactStorage + Clone>(elements: &[T]) -> CompactVec<T> {
1322        let mut vec: CompactVec<T> = CompactVec::new();
1323        for elem in elements {
1324            vec.push(*elem);
1325        }
1326        vec
1327    }
1328
1329    #[test]
1330    fn test_new() {
1331        let vec: CompactVec<i8> = CompactVec::new();
1332        assert_eq!(vec.len(), 0);
1333        assert!(vec.is_empty());
1334        assert!(vec.is_inline());
1335        assert_eq!(vec.capacity(), INLINE_CAPACITY);
1336    }
1337
1338    #[test]
1339    fn test_default() {
1340        let vec: CompactVec<i8> = CompactVec::default();
1341        assert_eq!(vec.len(), 0);
1342        assert!(vec.is_empty());
1343        assert!(vec.is_inline());
1344    }
1345
1346    #[test]
1347    fn test_push_inline() {
1348        let mut vec: CompactVec<i8> = CompactVec::new();
1349
1350        // Test pushing elements within inline capacity
1351        for i in 0..INLINE_CAPACITY as i8 {
1352            vec.push(i);
1353            assert_eq!(vec.len(), (i + 1) as usize);
1354            assert!(vec.is_inline());
1355            assert_eq!(vec.get(i as usize), Some(i));
1356        }
1357
1358        assert_eq!(vec.len(), INLINE_CAPACITY);
1359        assert!(vec.is_inline());
1360    }
1361
1362    #[test]
1363    fn test_push_transition_to_heap() {
1364        let mut vec: CompactVec<i8> = CompactVec::new();
1365
1366        // Fill inline storage
1367        for i in 0..INLINE_CAPACITY as i8 {
1368            vec.push(i);
1369        }
1370        assert!(vec.is_inline());
1371
1372        // This should trigger transition to heap
1373        vec.push(INLINE_CAPACITY as i8);
1374        assert!(!vec.is_inline());
1375        assert_eq!(vec.len(), INLINE_CAPACITY + 1);
1376        assert!(vec.capacity() > INLINE_CAPACITY);
1377
1378        // Verify all elements are still accessible
1379        for i in 0..=INLINE_CAPACITY as i8 {
1380            assert_eq!(vec.get(i as usize), Some(i));
1381        }
1382    }
1383
1384    #[test]
1385    fn test_push_unchecked() {
1386        let mut vec: CompactVec<i8> = CompactVec::new();
1387
1388        vec.push_unchecked(42);
1389        vec.push_unchecked(-10);
1390
1391        assert_eq!(vec.len(), 2);
1392        assert_eq!(vec.get(0), Some(42));
1393        assert_eq!(vec.get(1), Some(-10));
1394    }
1395
1396    #[test]
1397    fn test_pop() {
1398        let mut vec: CompactVec<i8> = CompactVec::new();
1399
1400        // Pop from empty vector
1401        assert_eq!(vec.pop(), None);
1402
1403        // Push some elements and pop them
1404        vec.push(1);
1405        vec.push(2);
1406        vec.push(3);
1407
1408        assert_eq!(vec.pop(), Some(3));
1409        assert_eq!(vec.len(), 2);
1410        assert_eq!(vec.pop(), Some(2));
1411        assert_eq!(vec.pop(), Some(1));
1412        assert_eq!(vec.len(), 0);
1413        assert_eq!(vec.pop(), None);
1414    }
1415
1416    #[test]
1417    fn test_get_and_bounds() {
1418        let vec = test_vec_with_elements(&[1i8, 2, 3]);
1419
1420        assert_eq!(vec.get(0), Some(1));
1421        assert_eq!(vec.get(1), Some(2));
1422        assert_eq!(vec.get(2), Some(3));
1423        assert_eq!(vec.get(3), None);
1424        assert_eq!(vec.get(100), None);
1425    }
1426
1427    #[test]
1428    fn test_get_unchecked() {
1429        let vec = test_vec_with_elements(&[42i8, -10, 100]);
1430
1431        unsafe {
1432            assert_eq!(vec.get_unchecked(0), 42);
1433            assert_eq!(vec.get_unchecked(1), -10);
1434            assert_eq!(vec.get_unchecked(2), 100);
1435        }
1436    }
1437
1438    #[test]
1439    fn test_capacity() {
1440        let mut vec: CompactVec<i8> = CompactVec::new();
1441        assert_eq!(vec.capacity(), INLINE_CAPACITY);
1442
1443        // Fill to capacity
1444        for i in 0..INLINE_CAPACITY as i8 {
1445            vec.push(i);
1446        }
1447        assert_eq!(vec.capacity(), INLINE_CAPACITY);
1448
1449        // Transition to heap
1450        vec.push(INLINE_CAPACITY as i8);
1451        assert!(vec.capacity() > INLINE_CAPACITY);
1452    }
1453
1454    #[test]
1455    fn test_remove() {
1456        let mut vec = test_vec_with_elements(&[1i8, 2, 3, 4, 5]);
1457
1458        // Remove from middle
1459        assert_eq!(vec.remove(2), 3);
1460        assert_eq!(vec.len(), 4);
1461        assert_eq!(vec.get(2), Some(4));
1462
1463        // Remove first element
1464        assert_eq!(vec.remove(0), 1);
1465        assert_eq!(vec.len(), 3);
1466        assert_eq!(vec.get(0), Some(2));
1467
1468        // Remove last element
1469        assert_eq!(vec.remove(2), 5);
1470        assert_eq!(vec.len(), 2);
1471    }
1472
1473    #[test]
1474    #[should_panic(expected = "removal index")]
1475    fn test_remove_out_of_bounds() {
1476        let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
1477        vec.remove(3);
1478    }
1479
1480    #[test]
1481    fn test_insert() {
1482        let mut vec = test_vec_with_elements(&[1i8, 3, 4]);
1483
1484        // Insert at middle
1485        vec.insert(1, 2);
1486        assert_eq!(vec.len(), 4);
1487        assert_eq!(vec.get(0), Some(1));
1488        assert_eq!(vec.get(1), Some(2));
1489        assert_eq!(vec.get(2), Some(3));
1490        assert_eq!(vec.get(3), Some(4));
1491
1492        // Insert at beginning
1493        vec.insert(0, 0);
1494        assert_eq!(vec.len(), 5);
1495        assert_eq!(vec.get(0), Some(0));
1496
1497        // Insert at end
1498        vec.insert(5, 5);
1499        assert_eq!(vec.len(), 6);
1500        assert_eq!(vec.get(5), Some(5));
1501    }
1502
1503    #[test]
1504    #[should_panic(expected = "insertion index")]
1505    fn test_insert_out_of_bounds() {
1506        let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
1507        vec.insert(4, 42);
1508    }
1509
1510    #[test]
1511    fn test_truncate() {
1512        let mut vec = test_vec_with_elements(&[1i8, 2, 3, 4, 5]);
1513
1514        vec.truncate(3);
1515        assert_eq!(vec.len(), 3);
1516        assert_eq!(vec.get(2), Some(3));
1517        assert_eq!(vec.get(3), None);
1518
1519        // Truncate to larger size should have no effect
1520        vec.truncate(10);
1521        assert_eq!(vec.len(), 3);
1522
1523        // Truncate to 0
1524        vec.truncate(0);
1525        assert_eq!(vec.len(), 0);
1526        assert!(vec.is_empty());
1527    }
1528
1529    #[test]
1530    fn test_resize() {
1531        let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
1532
1533        // Resize larger
1534        vec.resize(5, 42);
1535        assert_eq!(vec.len(), 5);
1536        assert_eq!(vec.get(3), Some(42));
1537        assert_eq!(vec.get(4), Some(42));
1538
1539        // Resize smaller
1540        vec.resize(2, 99);
1541        assert_eq!(vec.len(), 2);
1542        assert_eq!(vec.get(1), Some(2));
1543        assert_eq!(vec.get(2), None);
1544    }
1545
1546    #[test]
1547    fn test_extend_from_slice() {
1548        let mut vec = test_vec_with_elements(&[1i8, 2]);
1549
1550        vec.extend_from_slice(&[3, 4, 5]);
1551        assert_eq!(vec.len(), 5);
1552        assert_eq!(vec.get(2), Some(3));
1553        assert_eq!(vec.get(3), Some(4));
1554        assert_eq!(vec.get(4), Some(5));
1555
1556        // Extend to force heap transition
1557        vec.extend_from_slice(&[6, 7, 8]);
1558        assert_eq!(vec.len(), 8);
1559        assert!(!vec.is_inline());
1560    }
1561
1562    #[test]
1563    fn test_reserve() {
1564        let mut vec: CompactVec<i8> = CompactVec::new();
1565
1566        // Reserve within inline capacity
1567        vec.reserve(5);
1568        assert!(vec.is_inline());
1569
1570        // Reserve beyond inline capacity
1571        vec.reserve(10);
1572        assert!(!vec.is_inline());
1573        assert!(vec.capacity() >= 10);
1574    }
1575
1576    #[test]
1577    fn test_clear() {
1578        let mut vec = test_vec_with_elements(&[1i8, 2, 3, 4, 5]);
1579        let was_inline = vec.is_inline();
1580
1581        vec.clear();
1582        assert_eq!(vec.len(), 0);
1583        assert!(vec.is_empty());
1584        assert_eq!(vec.is_inline(), was_inline); // Storage mode should remain the same
1585    }
1586
1587    #[test]
1588    fn test_contains_method() {
1589        let mut vec: CompactVec<i8> = CompactVec::new();
1590        vec.push(1);
1591        vec.push(2);
1592        vec.push(3);
1593
1594        assert!(vec.contains(&1));
1595        assert!(vec.contains(&2));
1596        assert!(vec.contains(&3));
1597        assert!(!vec.contains(&4));
1598        assert!(!vec.contains(&0));
1599    }
1600
1601    #[test]
1602    fn test_sort() {
1603        let mut vec = test_vec_with_elements(&[3i8, 1, 4, 1, 5]);
1604
1605        vec.sort();
1606        assert_eq!(vec.get(0), Some(1));
1607        assert_eq!(vec.get(1), Some(1));
1608        assert_eq!(vec.get(2), Some(3));
1609        assert_eq!(vec.get(3), Some(4));
1610        assert_eq!(vec.get(4), Some(5));
1611    }
1612
1613    #[test]
1614    fn test_take() {
1615        let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
1616
1617        let taken = vec.take();
1618        assert_eq!(taken.len(), 3);
1619        assert_eq!(vec.len(), 0);
1620        assert!(vec.is_empty());
1621        assert!(vec.is_inline());
1622    }
1623
1624    #[test]
1625    fn test_as_slice_i8() {
1626        let vec = test_vec_with_elements(&[1i8, 2, 3]);
1627        let slice = vec.as_slice();
1628        assert_eq!(slice, &[1, 2, 3]);
1629    }
1630
1631    #[test]
1632    fn test_get_mut_i8() {
1633        let mut vec = test_vec_with_elements(&[10i8, 20, 30]);
1634
1635        if let Some(elem) = vec.get_mut(1) {
1636            *elem = 25;
1637        }
1638        assert_eq!(vec.get(1), Some(25));
1639    }
1640
1641    #[test]
1642    fn test_get_mut_unchecked_i8() {
1643        let mut vec = test_vec_with_elements(&[42i8]);
1644
1645        unsafe {
1646            *vec.get_mut_unchecked(0) = 100;
1647        }
1648        assert_eq!(vec.get(0), Some(100));
1649    }
1650
1651    #[test]
1652    fn test_as_slice_mut_i8() {
1653        let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
1654
1655        let slice = vec.as_slice_mut();
1656        slice[1] = 10;
1657        assert_eq!(vec.get(1), Some(10));
1658    }
1659
1660    #[test]
1661    fn test_iter() {
1662        let vec = test_vec_with_elements(&[1i8, 2, 3, 4, 5]);
1663
1664        let collected: Vec<i8> = vec.iter().collect();
1665        assert_eq!(collected, vec![1, 2, 3, 4, 5]);
1666
1667        let sum: i8 = vec.iter().sum();
1668        assert_eq!(sum, 15);
1669    }
1670
1671    #[test]
1672    fn test_iter_size_hint() {
1673        let vec = test_vec_with_elements(&[1i8, 2, 3]);
1674        let mut iter = vec.iter();
1675
1676        assert_eq!(iter.size_hint(), (3, Some(3)));
1677        iter.next();
1678        assert_eq!(iter.size_hint(), (2, Some(2)));
1679    }
1680
1681    #[test]
1682    fn test_into_iter() {
1683        let vec = test_vec_with_elements(&[1i8, 2, 3]);
1684
1685        let collected: Vec<i8> = vec.into_iter().collect();
1686        assert_eq!(collected, vec![1, 2, 3]);
1687    }
1688
1689    #[test]
1690    fn test_into_iter_ref() {
1691        let vec = test_vec_with_elements(&[1i8, 2, 3]);
1692
1693        let collected: Vec<i8> = (&vec).into_iter().collect();
1694        assert_eq!(collected, vec![1, 2, 3]);
1695        assert_eq!(vec.len(), 3); // Original should still exist
1696    }
1697
1698    #[test]
1699    fn test_into_iter_mut() {
1700        let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
1701
1702        for elem in &mut vec {
1703            *elem *= 2;
1704        }
1705
1706        assert_eq!(vec.get(0), Some(2));
1707        assert_eq!(vec.get(1), Some(4));
1708        assert_eq!(vec.get(2), Some(6));
1709    }
1710
1711    #[test]
1712    fn test_from_vec() {
1713        let vec = vec![1i8, 2, 3, 4, 5];
1714        let compact: CompactVec<i8> = vec.into();
1715
1716        assert_eq!(compact.len(), 5);
1717        assert!(compact.is_inline());
1718        assert_eq!(compact.get(0), Some(1));
1719        assert_eq!(compact.get(4), Some(5));
1720    }
1721
1722    #[test]
1723    fn test_from_array() {
1724        let array = [1i8, 2, 3, 4, 5];
1725        let compact: CompactVec<i8> = array.into();
1726
1727        assert_eq!(compact.len(), 5);
1728        assert_eq!(compact.get(0), Some(1));
1729        assert_eq!(compact.get(4), Some(5));
1730    }
1731
1732    #[test]
1733    fn test_from_array_ref() {
1734        let array = [1i8, 2, 3, 4, 5];
1735        let compact: CompactVec<i8> = (&array).into();
1736
1737        assert_eq!(compact.len(), 5);
1738        assert_eq!(compact.get(0), Some(1));
1739        assert_eq!(compact.get(4), Some(5));
1740    }
1741
1742    #[test]
1743    fn test_from_slice() {
1744        let slice = &[1i8, 2, 3];
1745        let compact: CompactVec<i8> = slice.into();
1746
1747        assert_eq!(compact.len(), 3);
1748        assert_eq!(compact.get(0), Some(1));
1749        assert_eq!(compact.get(2), Some(3));
1750    }
1751
1752    #[test]
1753    fn test_into_vec() {
1754        let compact = test_vec_with_elements(&[1i8, 2, 3]);
1755        let vec: Vec<i8> = compact.into();
1756
1757        assert_eq!(vec, vec![1, 2, 3]);
1758    }
1759
1760    #[test]
1761    fn test_deref_i8() {
1762        let vec = test_vec_with_elements(&[1i8, 2, 3]);
1763        let slice: &[i8] = &vec; // Uses Deref
1764
1765        assert_eq!(slice, &[1, 2, 3]);
1766    }
1767
1768    #[test]
1769    fn test_index_i8() {
1770        let vec = test_vec_with_elements(&[10i8, 20, 30]);
1771
1772        assert_eq!(vec[0], 10);
1773        assert_eq!(vec[1], 20);
1774        assert_eq!(vec[2], 30);
1775    }
1776
1777    #[test]
1778    #[should_panic(expected = "index out of bounds")]
1779    fn test_index_out_of_bounds() {
1780        let vec = test_vec_with_elements(&[1i8, 2, 3]);
1781        let _ = vec[3];
1782    }
1783
1784    #[test]
1785    fn test_as_ref_i8() {
1786        let vec = test_vec_with_elements(&[1i8, 2, 3]);
1787        let slice: &[i8] = vec.as_ref();
1788
1789        assert_eq!(slice, &[1, 2, 3]);
1790    }
1791
1792    #[test]
1793    fn test_as_mut_trait() {
1794        let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
1795        let slice: &mut [i8] = vec.as_mut();
1796
1797        slice[1] = 42;
1798        assert_eq!(vec.get(1), Some(42));
1799    }
1800
1801    #[test]
1802    fn test_heap_operations() {
1803        let mut vec: CompactVec<i8> = CompactVec::new();
1804
1805        // Fill beyond inline capacity to force heap
1806        for i in 0..10 {
1807            vec.push(i);
1808        }
1809
1810        assert!(!vec.is_inline());
1811        assert_eq!(vec.len(), 10);
1812
1813        // Test operations on heap storage
1814        assert_eq!(vec.pop(), Some(9));
1815        assert_eq!(vec.get(5), Some(5));
1816
1817        vec.insert(5, 42);
1818        assert_eq!(vec.get(5), Some(42));
1819
1820        let removed = vec.remove(5);
1821        assert_eq!(removed, 42);
1822    }
1823
1824    #[test]
1825    fn test_empty_operations() {
1826        let mut vec: CompactVec<i8> = CompactVec::new();
1827
1828        assert_eq!(vec.pop(), None);
1829        assert_eq!(vec.get(0), None);
1830        assert!(vec.is_empty());
1831        assert_eq!(vec.len(), 0);
1832
1833        let iter_count = vec.iter().count();
1834        assert_eq!(iter_count, 0);
1835    }
1836
1837    #[test]
1838    fn test_clone() {
1839        let vec = test_vec_with_elements(&[1i8, 2, 3]);
1840        let cloned = vec.clone();
1841
1842        assert_eq!(vec.len(), cloned.len());
1843        assert_eq!(vec.is_inline(), cloned.is_inline());
1844
1845        for i in 0..vec.len() {
1846            assert_eq!(vec.get(i), cloned.get(i));
1847        }
1848    }
1849
1850    #[test]
1851    fn test_u8_specialization() {
1852        let mut vec: CompactVec<u8> = CompactVec::new();
1853        vec.extend_from_slice(&[1u8, 2, 3]);
1854
1855        // Test u8 specific deref
1856        let slice: &[u8] = &vec;
1857        assert_eq!(slice, &[1u8, 2, 3]);
1858
1859        // Test u8 indexing
1860        assert_eq!(vec[1], 2u8);
1861
1862        // Test u8 as_ref
1863        let slice: &[u8] = vec.as_ref();
1864        assert_eq!(slice, &[1u8, 2, 3]);
1865    }
1866
1867    #[test]
1868    fn test_debug() {
1869        let vec = test_vec_with_elements(&[1i8, 2, 3]);
1870        let debug_str = format!("{:?}", vec);
1871
1872        // Just ensure it doesn't panic and produces some output
1873        assert!(!debug_str.is_empty());
1874    }
1875
1876    #[test]
1877    fn test_from_iterator() {
1878        let iter = 0..5;
1879        let vec: CompactVec<i8> = iter.collect();
1880        assert_eq!(vec.len(), 5);
1881        assert_eq!(vec.as_slice(), &[0, 1, 2, 3, 4]);
1882
1883        let empty_iter: std::vec::IntoIter<i8> = Vec::new().into_iter();
1884        let empty_vec: CompactVec<i8> = empty_iter.collect();
1885        assert_eq!(empty_vec.len(), 0);
1886    }
1887
1888    #[test]
1889    fn test_transition_preserves_order() {
1890        let mut vec: CompactVec<i8> = CompactVec::new();
1891
1892        // Add elements that will fill inline storage
1893        for i in 0..INLINE_CAPACITY {
1894            vec.push((i * 10) as i8);
1895        }
1896        assert!(vec.is_inline());
1897
1898        // Force transition to heap
1899        vec.push((INLINE_CAPACITY * 10) as i8);
1900        assert!(!vec.is_inline());
1901
1902        // Verify all elements are in correct order
1903        for i in 0..=INLINE_CAPACITY {
1904            assert_eq!(vec.get(i), Some((i as i8) * 10));
1905        }
1906    }
1907}