Skip to main content

layout/
compact.rs

1//! Compact (bit-packed) columns for struct-of-arrays layouts.
2//!
3//! [`Compact<T>`] is the owning value wrapper that marks a field for
4//! compaction. When a struct containing a `Compact<T>` field is derived with
5//! `#[derive(SOA)]`, that column is stored bit-packed (one `T` per
6//! [`CompactRepr::BITS`] bits) instead of as a `Vec<T>`.
7//!
8//! `T` must implement [`CompactRepr`]. This is implemented for `bool` (1 bit)
9//! and, via `#[derive(CompactRepr)]`, for any fieldless enum with an unsigned
10//! `#[repr(uN)]` repr (2 / 4 bits depending on the largest discriminant).
11//!
12//! # Access
13//!
14//! Access is uniform across the owning value, the immutable generated `Ref`
15//! and the mutable generated `RefMut`, so the same expression works in a
16//! `#[soa_impl]` method body whether it is invoked on the owned struct, the
17//! generated `Ref` or the generated `RefMut`:
18//!
19//! * **read**: `self.flag.get()`
20//! * **write** (mutable only): `self.flag.set(value)`
21//!
22//! No dereference or write-back-on-drop is involved: a mutable handle writes
23//! the packed word immediately.
24
25use core::{marker::PhantomData, ops::Range};
26
27use crate::bitpack::BitPack;
28
29/// Bit-packed backing store type backing a `T` compact column.
30type Store<T> = <T as CompactRepr>::Storage;
31
32/// Compact representation: how a `Copy` value is encoded into and decoded
33/// from a small unsigned integer, and which [`BitPack`] storage backs it.
34///
35/// Implemented for `bool` (1 bit) and, via `#[derive(CompactRepr)]`, for
36/// fieldless enums. Implementors (and their storage) must be `'static` so that
37/// borrowed column views of any lifetime are well-formed.
38pub trait CompactRepr: Copy + Sized + 'static {
39    /// The bit-packed storage backing a column of this type. Each impl picks
40    /// a concrete `PackedArray<N>`.
41    type Storage: BitPack + 'static;
42
43    /// Number of bits used per element (`1` for `bool`; `2`/`4` for enums).
44    const BITS: u32;
45
46    /// Encode `self` into the raw integer stored in the packed words.
47    fn encode(self) -> usize;
48
49    /// Decode a raw integer read from the packed words back into a value.
50    ///
51    /// # Safety contract (implementors)
52    /// `raw` is always a value previously produced by [`encode`](Self::encode),
53    /// since the compact column never stores anything else.
54    fn decode(raw: usize) -> Self;
55}
56
57impl CompactRepr for bool {
58    type Storage = crate::bitpack::PackedArray<1>;
59    const BITS: u32 = 1;
60
61    #[inline(always)]
62    fn encode(self) -> usize {
63        self as usize
64    }
65
66    #[inline(always)]
67    fn decode(raw: usize) -> Self {
68        raw != 0
69    }
70}
71
72// ---------------------------------------------------------------------------
73// Compact<T> - owning value
74// ---------------------------------------------------------------------------
75
76/// Owning compact value. Marks a struct field for bit-packed storage when the
77/// containing struct is derived with `#[derive(SOA)]`.
78#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
79pub struct Compact<T: CompactRepr>(pub T);
80
81/// 1-bit compact boolean, for backwards-compatible naming.
82pub type CompactBool = Compact<bool>;
83
84impl<T: CompactRepr> Compact<T> {
85    /// Wrap a value for compact storage.
86    #[inline(always)]
87    pub fn new(value: T) -> Self {
88        Compact(value)
89    }
90
91    /// Read the contained value.
92    #[inline(always)]
93    pub fn get(&self) -> T {
94        self.0
95    }
96
97    /// Overwrite the contained value.
98    #[inline(always)]
99    pub fn set(&mut self, value: T) {
100        self.0 = value;
101    }
102
103    /// Build a mutable handle to this value (used by the generated `RefMut`
104    /// construction). Writes through the handle propagate back here
105    /// immediately via [`CompactRefMut::set`].
106    #[inline(always)]
107    pub fn as_mut(&mut self) -> CompactRefMut<'_, T> {
108        CompactRefMut::from_value(&mut self.0)
109    }
110
111    /// Returns a direct pointer to this value, so an element pointer derived
112    /// from a `Ref` is never misclassified as null. Unlike column pointers,
113    /// it is valid only while this `Compact` lives (for the compact field of
114    /// a `Ref`, that is the `Ref` itself, not the underlying vec).
115    #[inline(always)]
116    pub fn as_ptr(&self) -> CompactPtr<T> {
117        CompactPtr {
118            packed: (&self.0 as *const T).cast(),
119            index: DIRECT_INDEX,
120        }
121    }
122}
123
124impl<T: CompactRepr> From<T> for Compact<T> {
125    #[inline(always)]
126    fn from(value: T) -> Self {
127        Compact(value)
128    }
129}
130
131// `Compact<T>` is a transparent storage marker around a `Copy` value, so it
132// dereferences to the value: `*c`, `c.method()` and `c == value` all work
133// without unwrapping.
134impl<T: CompactRepr> core::ops::Deref for Compact<T> {
135    type Target = T;
136    #[inline(always)]
137    fn deref(&self) -> &T {
138        &self.0
139    }
140}
141
142impl<T: CompactRepr> core::ops::DerefMut for Compact<T> {
143    #[inline(always)]
144    fn deref_mut(&mut self) -> &mut T {
145        &mut self.0
146    }
147}
148
149impl<T: CompactRepr + PartialEq> PartialEq<T> for Compact<T> {
150    #[inline(always)]
151    fn eq(&self, other: &T) -> bool {
152        self.0 == *other
153    }
154}
155
156impl<T: CompactRepr + PartialOrd> PartialOrd<T> for Compact<T> {
157    #[inline(always)]
158    fn partial_cmp(&self, other: &T) -> Option<core::cmp::Ordering> {
159        self.0.partial_cmp(other)
160    }
161}
162
163#[cfg(feature = "serde")]
164impl<T: CompactRepr + serde::Serialize> serde::Serialize for Compact<T> {
165    fn serialize<S: serde::Serializer>(
166        &self,
167        serializer: S,
168    ) -> Result<S::Ok, S::Error> {
169        self.0.serialize(serializer)
170    }
171}
172
173#[cfg(feature = "serde")]
174impl<'de, T: CompactRepr + serde::Deserialize<'de>> serde::Deserialize<'de>
175    for Compact<T>
176{
177    fn deserialize<D: serde::Deserializer<'de>>(
178        deserializer: D,
179    ) -> Result<Self, D::Error> {
180        T::deserialize(deserializer).map(Compact)
181    }
182}
183
184// ---------------------------------------------------------------------------
185// CompactRefMut - read/write handle to a single packed (or owned) element.
186// No Deref, no Drop: get() reads live, set() writes immediately.
187// ---------------------------------------------------------------------------
188
189pub struct CompactRefMut<'a, T: CompactRepr> {
190    // Storage-backed mode: `packed` points at the column store and `index`
191    // addresses the lane. Direct mode (`index == DIRECT_INDEX`): `packed` is
192    // a disguised `*mut T` to a standalone owned value. The same sentinel
193    // scheme as `CompactPtr` keeps the handle at two words.
194    packed: *mut Store<T>,
195    index: usize,
196    _marker: PhantomData<&'a mut ()>,
197}
198
199impl<'a, T: CompactRepr> CompactRefMut<'a, T> {
200    #[inline(always)]
201    pub(crate) fn from_packed(packed: &'a mut Store<T>, index: usize) -> Self {
202        Self {
203            packed: packed as *mut Store<T>,
204            index,
205            _marker: PhantomData,
206        }
207    }
208
209    /// Construct a handle from a raw pointer to packed storage.
210    ///
211    /// # Safety
212    /// `packed` must point to a live, properly aligned `Store<T>` whose length
213    /// exceeds `index` for the handle's lifetime; the resulting handle must not
214    /// outlive that storage.
215    #[inline(always)]
216    pub(crate) unsafe fn from_packed_ptr(
217        packed: *mut Store<T>,
218        index: usize,
219    ) -> Self {
220        Self {
221            packed,
222            index,
223            _marker: PhantomData,
224        }
225    }
226
227    #[inline(always)]
228    fn from_value(value: &'a mut T) -> Self {
229        Self {
230            packed: (value as *mut T).cast(),
231            index: DIRECT_INDEX,
232            _marker: PhantomData,
233        }
234    }
235
236    /// Read the current value live from the backing storage.
237    #[inline]
238    pub fn get(&self) -> T {
239        // The packed (column) path is the overwhelmingly common one; the
240        // direct path only fires for an owned value viewed as a RefMut.
241        if ::branches::likely(self.index != DIRECT_INDEX) {
242            // SAFETY: `packed` aliases borrowed storage that is still live;
243            // `index` is in bounds by construction.
244            unsafe { T::decode((*self.packed).get_unchecked(self.index)) }
245        } else {
246            // SAFETY: `packed` disguises the borrowed `&mut T`, still live.
247            unsafe { *self.packed.cast::<T>() }
248        }
249    }
250
251    /// Write `value` to the backing storage immediately.
252    #[inline]
253    pub fn set(&mut self, value: T) {
254        if ::branches::likely(self.index != DIRECT_INDEX) {
255            // SAFETY: as above.
256            unsafe {
257                (*self.packed).set_unchecked(self.index, T::encode(value));
258            }
259        } else {
260            // SAFETY: as above.
261            unsafe {
262                *self.packed.cast::<T>() = value;
263            }
264        }
265    }
266
267    #[inline]
268    pub fn to_owned(&self) -> Compact<T> {
269        Compact::new(self.get())
270    }
271
272    pub fn replace(&mut self, val: Compact<T>) -> Compact<T> {
273        let old = Compact::new(self.get());
274        self.set(val.0);
275        old
276    }
277
278    pub fn as_ptr(&self) -> CompactPtr<T> {
279        // Both modes carry over verbatim (the sentinel travels in `index`).
280        CompactPtr {
281            packed: self.packed as *const Store<T>,
282            index: self.index,
283        }
284    }
285
286    pub fn as_mut_ptr(&mut self) -> CompactPtrMut<T> {
287        CompactPtrMut {
288            packed: self.packed,
289            index: self.index,
290        }
291    }
292}
293
294impl<T: CompactRepr + core::fmt::Debug> core::fmt::Debug
295    for CompactRefMut<'_, T>
296{
297    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
298        f.debug_struct("CompactRefMut")
299            .field("value", &self.get())
300            .finish()
301    }
302}
303
304impl<'a, T: CompactRepr + PartialEq> PartialEq for CompactRefMut<'a, T> {
305    fn eq(&self, other: &Self) -> bool {
306        self.get() == other.get()
307    }
308}
309
310impl<'a, T: CompactRepr + Eq> Eq for CompactRefMut<'a, T> {}
311
312impl<'a, T: CompactRepr + core::hash::Hash> core::hash::Hash
313    for CompactRefMut<'a, T>
314{
315    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
316        self.get().hash(state);
317    }
318}
319
320impl<'a, T: CompactRepr> From<CompactRefMut<'a, T>> for Compact<T> {
321    #[inline]
322    fn from(value: CompactRefMut<'a, T>) -> Self {
323        value.to_owned()
324    }
325}
326
327impl<'a, T: CompactRepr> From<&'a CompactRefMut<'a, T>> for Compact<T> {
328    #[inline]
329    fn from(value: &'a CompactRefMut<'a, T>) -> Self {
330        value.to_owned()
331    }
332}
333
334// ---------------------------------------------------------------------------
335// Trait wiring: Compact<T> behaves as a nested SoA column.
336// ---------------------------------------------------------------------------
337
338impl<T: CompactRepr> crate::SOA for Compact<T> {
339    type Type = CompactVec<T>;
340}
341
342impl<'a, T: CompactRepr> crate::SoAIter<'a> for Compact<T> {
343    type Ref = Compact<T>;
344    type RefMut = CompactRefMut<'a, T>;
345    type Iter = CompactIter<'a, T>;
346    type IterMut = CompactIterMut<'a, T>;
347}
348
349impl<T: CompactRepr> crate::SoAPointers for Compact<T> {
350    type Ptr = CompactPtr<T>;
351    type MutPtr = CompactPtrMut<T>;
352}
353
354// ---------------------------------------------------------------------------
355// CompactVec
356// ---------------------------------------------------------------------------
357
358pub struct CompactVec<T: CompactRepr> {
359    inner: Store<T>,
360}
361
362impl<T: CompactRepr> Default for CompactVec<T> {
363    #[inline]
364    fn default() -> Self {
365        Self {
366            inner: Default::default(),
367        }
368    }
369}
370
371impl<T: CompactRepr + core::fmt::Debug> core::fmt::Debug for CompactVec<T> {
372    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
373        f.debug_list()
374            .entries(
375                (0..self.len()).map(|i| Compact(T::decode(self.inner.get(i)))),
376            )
377            .finish()
378    }
379}
380
381impl<T: CompactRepr> Clone for CompactVec<T> {
382    fn clone(&self) -> Self {
383        Self {
384            inner: self.inner.clone(),
385        }
386    }
387}
388
389impl<T: CompactRepr + PartialEq> PartialEq for CompactVec<T> {
390    fn eq(&self, other: &Self) -> bool {
391        self.len() == other.len()
392            && self.inner.range_eq(0, &other.inner, 0, self.len())
393    }
394}
395
396impl<T: CompactRepr + Eq> Eq for CompactVec<T> {}
397
398impl<T: CompactRepr + core::hash::Hash> core::hash::Hash for CompactVec<T> {
399    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
400        self.len().hash(state);
401        for i in 0..self.len() {
402            self.inner.get(i).hash(state);
403        }
404    }
405}
406
407impl<T: CompactRepr> core::iter::FromIterator<Compact<T>> for CompactVec<T> {
408    fn from_iter<I: IntoIterator<Item = Compact<T>>>(iter: I) -> Self {
409        let iterator = iter.into_iter();
410        // Lower bound like `std`'s `collect`: a filter's upper bound is the
411        // source length, so reserving it over-allocates the packed store.
412        let mut result = CompactVec::<T>::with_capacity(iterator.size_hint().0);
413        for item in iterator {
414            result.push(item);
415        }
416        result
417    }
418}
419
420impl<T: CompactRepr> core::iter::Extend<Compact<T>> for CompactVec<T> {
421    fn extend<I: IntoIterator<Item = Compact<T>>>(&mut self, iter: I) {
422        let iterator = iter.into_iter();
423        self.reserve(iterator.size_hint().0);
424        for item in iterator {
425            self.push(item);
426        }
427    }
428}
429
430#[allow(dead_code)]
431impl<T: CompactRepr> CompactVec<T> {
432    #[inline]
433    pub fn new() -> Self {
434        Self::default()
435    }
436
437    #[inline]
438    pub fn with_capacity(capacity: usize) -> Self {
439        Self {
440            inner: Store::<T>::with_capacity(capacity),
441        }
442    }
443
444    #[inline]
445    pub fn len(&self) -> usize {
446        self.inner.len()
447    }
448
449    #[inline]
450    pub fn is_empty(&self) -> bool {
451        self.inner.is_empty()
452    }
453
454    #[inline]
455    pub fn capacity(&self) -> usize {
456        self.inner.capacity()
457    }
458
459    #[inline]
460    pub fn reserve(&mut self, additional: usize) {
461        self.inner.reserve(additional);
462    }
463
464    #[inline]
465    pub fn reserve_exact(&mut self, additional: usize) {
466        self.inner.reserve_exact(additional);
467    }
468
469    #[inline]
470    pub fn shrink_to_fit(&mut self) {
471        self.inner.shrink_to_fit();
472    }
473
474    #[inline]
475    pub fn push(&mut self, value: impl Into<Compact<T>>) {
476        self.inner.push(T::encode(value.into().0));
477    }
478
479    #[inline]
480    pub fn pop(&mut self) -> Option<Compact<T>> {
481        self.inner.pop().map(|w| Compact(T::decode(w)))
482    }
483
484    pub fn insert(&mut self, index: usize, element: impl Into<Compact<T>>) {
485        let element = element.into();
486        assert!(
487            index <= self.len(),
488            "insertion index (is {}) should be <= len (is {})",
489            index,
490            self.len()
491        );
492        // Grow by one (the pushed value is immediately overwritten by the
493        // shift), then move the tail up one lane word-at-a-time.
494        self.push(Compact::new(element.0));
495        let len = self.len();
496        self.inner.copy_lanes(index, index + 1, len - 1 - index);
497        // SAFETY: `index < len` (the column just grew past `index <= len`).
498        unsafe { self.inner.set_unchecked(index, T::encode(element.0)) };
499    }
500
501    pub fn remove(&mut self, index: usize) -> Compact<T> {
502        assert!(
503            index < self.len(),
504            "index out of bounds: the len is {} but the index is {}",
505            self.len(),
506            index
507        );
508        // SAFETY: `index < self.len()` was asserted above.
509        let val =
510            unsafe { Compact(T::decode(self.inner.get_unchecked(index))) };
511        // Move the tail down one lane word-at-a-time, then drop the last.
512        let len = self.len();
513        self.inner.copy_lanes(index + 1, index, len - 1 - index);
514        self.inner.pop();
515        val
516    }
517
518    pub fn swap_remove(&mut self, index: usize) -> Compact<T> {
519        assert!(
520            index < self.len(),
521            "index out of bounds: the len is {} but the index is {}",
522            self.len(),
523            index
524        );
525        // SAFETY: `index < self.len()` was asserted above.
526        let val =
527            unsafe { Compact(T::decode(self.inner.get_unchecked(index))) };
528        let last = match self.inner.pop() {
529            Some(v) => v,
530            None => return val,
531        };
532        if index < self.inner.len() {
533            // SAFETY: `index < self.inner.len()` just checked.
534            unsafe { self.inner.set_unchecked(index, last) };
535        }
536        val
537    }
538
539    pub fn replace(
540        &mut self,
541        index: usize,
542        element: impl Into<Compact<T>>,
543    ) -> Compact<T> {
544        let element = element.into();
545        assert!(
546            index < self.len(),
547            "index out of bounds: the len is {} but the index is {}",
548            self.len(),
549            index
550        );
551        // SAFETY: `index < self.len()` was asserted above.
552        unsafe {
553            let old = Compact(T::decode(self.inner.get_unchecked(index)));
554            self.inner.set_unchecked(index, T::encode(element.0));
555            old
556        }
557    }
558
559    /// Set the element at `index` to `value`.
560    ///
561    /// # Panics
562    ///
563    /// Panics if `index >= self.len()`.
564    #[inline]
565    pub fn set(&mut self, index: usize, value: impl Into<Compact<T>>) {
566        let value = value.into();
567        assert!(
568            index < self.len(),
569            "index out of bounds: the len is {} but the index is {}",
570            self.len(),
571            index
572        );
573        // SAFETY: `index < self.len()` just asserted.
574        unsafe { self.inner.set_unchecked(index, T::encode(value.0)) };
575    }
576
577    #[inline]
578    pub fn truncate(&mut self, len: usize) {
579        self.inner.truncate(len);
580    }
581
582    /// Resizes the column to `new_len`, pushing copies of `value` to grow or
583    /// truncating to shrink (analogous to [`Vec::resize`]).
584    pub fn resize(&mut self, new_len: usize, value: impl Into<Compact<T>>) {
585        let value = value.into();
586        let cur = self.inner.len();
587        if new_len <= cur {
588            self.inner.truncate(new_len);
589        } else {
590            self.inner.extend_fill(T::encode(value.0), new_len - cur);
591        }
592    }
593
594    #[inline]
595    pub fn clear(&mut self) {
596        self.inner.clear();
597    }
598
599    pub fn split_off(&mut self, at: usize) -> CompactVec<T> {
600        assert!(
601            at <= self.len(),
602            "the len is {} but the index is {}",
603            self.len(),
604            at
605        );
606        let mut other = Store::<T>::with_capacity(self.len() - at);
607        other.extend_from_packed(&self.inner, at, self.inner.len() - at);
608        self.inner.truncate(at);
609        CompactVec { inner: other }
610    }
611
612    pub fn append(&mut self, other: &mut CompactVec<T>) {
613        self.inner.append(&mut other.inner);
614    }
615
616    /// Append every element of `other` to the end (analogous to
617    /// [`Vec::extend_from_slice`]). The generated `#[layout(Clone)]`
618    /// `extend_from_slice` dispatches here for compact columns.
619    pub fn extend_from_slice(&mut self, other: CompactSlice<'_, T>) {
620        if other.is_empty() {
621            return;
622        }
623        // SAFETY: `other.len() > 0` implies `other.packed` points at live
624        // storage; it cannot alias `self` (a shared borrow cannot coexist with
625        // this `&mut self`). Word-aligned ranges copy wholesale.
626        let src: &Store<T> = unsafe { &*other.packed };
627        self.inner.extend_from_packed(src, other.start, other.len());
628    }
629
630    pub fn as_slice(&self) -> CompactSlice<'_, T> {
631        CompactSlice {
632            packed: &self.inner as *const Store<T>,
633            start: 0,
634            len: self.inner.len(),
635            _marker: PhantomData,
636        }
637    }
638
639    pub fn as_mut_slice(&mut self) -> CompactSliceMut<'_, T> {
640        let len = self.inner.len();
641        CompactSliceMut {
642            packed: &mut self.inner as *mut Store<T>,
643            start: 0,
644            len,
645            _marker: PhantomData,
646        }
647    }
648
649    /// Iterate by value over the column (analogous to `Vec::iter`, yielding
650    /// `Compact<T>` snapshots). Also lets `soa_zip!` zip compact columns and
651    /// `for x in &compact_vec` compile.
652    #[inline]
653    pub fn iter(&self) -> CompactIter<'_, T> {
654        CompactIter::new(&self.inner as *const Store<T>, 0, self.inner.len())
655    }
656
657    /// Iterate by mutable handle over the column (analogous to
658    /// `Vec::iter_mut`).
659    #[inline]
660    pub fn iter_mut(&mut self) -> CompactIterMut<'_, T> {
661        CompactIterMut {
662            packed: &mut self.inner as *mut Store<T>,
663            pos: 0,
664            end: self.inner.len(),
665            _marker: PhantomData,
666        }
667    }
668
669    pub fn slice(&self, range: Range<usize>) -> CompactSlice<'_, T> {
670        assert!(range.start <= range.end && range.end <= self.len());
671        CompactSlice {
672            packed: &self.inner as *const Store<T>,
673            start: range.start,
674            len: range.end - range.start,
675            _marker: PhantomData,
676        }
677    }
678
679    pub fn slice_mut(&mut self, range: Range<usize>) -> CompactSliceMut<'_, T> {
680        assert!(range.start <= range.end && range.end <= self.len());
681        CompactSliceMut {
682            packed: &mut self.inner as *mut Store<T>,
683            start: range.start,
684            len: range.end - range.start,
685            _marker: PhantomData,
686        }
687    }
688
689    pub fn get(&self, index: usize) -> Option<Compact<T>> {
690        if index < self.inner.len() {
691            // SAFETY: `index < self.inner.len()` just checked.
692            Some(unsafe { Compact(T::decode(self.inner.get_unchecked(index))) })
693        } else {
694            None
695        }
696    }
697
698    /// Count elements equal to `value`. The value is encoded once and searched
699    /// for across the packed words; for 1-bit `T` (`bool` and 1-bit enums) this
700    /// uses `count_ones`/`count_zeros` over the words.
701    #[inline]
702    pub fn count(&self, value: T) -> usize {
703        self.inner.count_in(0, self.inner.len(), T::encode(value))
704    }
705
706    pub fn get_mut(&mut self, index: usize) -> Option<CompactRefMut<'_, T>> {
707        if index < self.inner.len() {
708            Some(CompactRefMut::from_packed(&mut self.inner, index))
709        } else {
710            None
711        }
712    }
713
714    pub fn as_ptr(&self) -> CompactPtr<T> {
715        CompactPtr {
716            packed: &self.inner as *const Store<T>,
717            index: 0,
718        }
719    }
720
721    pub fn as_mut_ptr(&mut self) -> CompactPtrMut<T> {
722        CompactPtrMut {
723            packed: &mut self.inner as *mut Store<T>,
724            index: 0,
725        }
726    }
727
728    /// Reconstruct a [`CompactVec`] from the raw packed-storage pointer
729    /// obtained from [`CompactVec::as_mut_ptr`].
730    ///
731    /// Unlike `Vec::from_raw_parts`, no `len`/`capacity` are required: the
732    /// [`PackedArray`](crate::bitpack::PackedArray) (`data.packed`) carries its
733    /// own element count and word-vector capacity.
734    ///
735    /// # Safety
736    /// `data` must originate from [`CompactVec::as_mut_ptr`], the source
737    /// [`CompactVec`] must have been forgotten (e.g. via [`core::mem::forget`])
738    /// and its storage not reused or freed since, and `data.packed` must still
739    /// point to valid, properly aligned `Store<T>` storage. This constructor
740    /// moves that storage out of the (forgotten) source, so the source must
741    /// never be used or dropped again.
742    pub unsafe fn from_raw_parts(data: CompactPtrMut<T>) -> CompactVec<T> {
743        CompactVec {
744            // SAFETY: `data.packed` points to a live, owned, inline
745            // `PackedArray` that the caller has given up (forgotten
746            // the source). We move it out by value; the source must
747            // not be dropped again.
748            inner: unsafe { core::ptr::read(data.packed) },
749        }
750    }
751
752    pub fn drain<R: core::ops::RangeBounds<usize>>(
753        &mut self,
754        range: R,
755    ) -> CompactDrain<'_, T> {
756        let start = match range.start_bound() {
757            core::ops::Bound::Included(&i) => i,
758            core::ops::Bound::Excluded(&i) => i + 1,
759            core::ops::Bound::Unbounded => 0,
760        };
761        let end = match range.end_bound() {
762            core::ops::Bound::Included(&i) => i + 1,
763            core::ops::Bound::Excluded(&i) => i,
764            core::ops::Bound::Unbounded => self.inner.len(),
765        };
766        assert!(start <= end && end <= self.inner.len());
767        let old_len = self.inner.len();
768        // Leak safety (mirrors `Vec::drain`): shorten to `start` up front
769        // while the drained lanes stay alive in the backing words. `Drop`
770        // shifts the tail down and restores the final length; a leaked drain
771        // leaves a short but consistent column, so sibling columns in a
772        // generated struct-of-arrays vec can never end up longer than this
773        // one.
774        //
775        // SAFETY: `start <= old_len`, so every lane `< start` is initialized
776        // and backed (`set_len` keeps the words alive).
777        unsafe { self.inner.set_len(start) };
778        CompactDrain {
779            packed: &mut self.inner,
780            drain_start: start,
781            drain_end: end,
782            old_len,
783            pos: start,
784            back: end,
785        }
786    }
787
788    /// Replace the elements in `range` with `replace_with`, returning the
789    /// removed elements as a (bit-packed) [`CompactVec`].
790    ///
791    /// Unlike [`Vec::splice`] this is eager, but both the removed elements
792    /// and the buffered replacement stay bit-packed, and the tail is shifted
793    /// with one word-level move.
794    pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> CompactVec<T>
795    where
796        R: core::ops::RangeBounds<usize>,
797        I: core::iter::IntoIterator<Item = Compact<T>>,
798    {
799        let start = match range.start_bound() {
800            core::ops::Bound::Included(&i) => i,
801            core::ops::Bound::Excluded(&i) => i + 1,
802            core::ops::Bound::Unbounded => 0,
803        };
804        let end = match range.end_bound() {
805            core::ops::Bound::Included(&i) => i + 1,
806            core::ops::Bound::Excluded(&i) => i,
807            core::ops::Bound::Unbounded => self.inner.len(),
808        };
809        assert!(
810            start <= end && end <= self.inner.len(),
811            "splice range out of bounds: the len is {} but the range is {}..{}",
812            self.inner.len(),
813            start,
814            end
815        );
816        let remove_count = end - start;
817        // Word-copy the removed range out while it is still contiguous.
818        let mut removed = Store::<T>::with_capacity(remove_count);
819        removed.extend_from_packed(&self.inner, start, remove_count);
820        // Buffer the replacement bit-packed (an iterator of unknown length
821        // cannot be written in place while the tail still occupies the
822        // range).
823        let iterator = replace_with.into_iter();
824        let mut replacement = Store::<T>::with_capacity(iterator.size_hint().0);
825        for item in iterator {
826            replacement.push(T::encode(item.0));
827        }
828        let insert_count = replacement.len();
829        if insert_count < remove_count {
830            let tail_len = self.inner.len() - end;
831            self.inner.copy_lanes(end, start + insert_count, tail_len);
832            self.inner
833                .truncate(self.inner.len() - (remove_count - insert_count));
834        } else {
835            for _ in 0..insert_count - remove_count {
836                self.inner.push(0);
837            }
838            let shift_from = start + remove_count;
839            let shift_to = start + insert_count;
840            let tail_len = self.inner.len() - shift_to;
841            self.inner.copy_lanes(shift_from, shift_to, tail_len);
842        }
843        for i in 0..insert_count {
844            // SAFETY: `start + i < start + insert_count <= self.len()` after
845            // the resize above.
846            unsafe {
847                self.inner
848                    .set_unchecked(start + i, replacement.get_unchecked(i));
849            }
850        }
851        CompactVec { inner: removed }
852    }
853}
854
855impl<'a, T: CompactRepr> IntoIterator for &'a CompactVec<T> {
856    type Item = Compact<T>;
857    type IntoIter = CompactIter<'a, T>;
858    #[inline]
859    fn into_iter(self) -> Self::IntoIter {
860        self.iter()
861    }
862}
863
864impl<'a, T: CompactRepr> IntoIterator for &'a mut CompactVec<T> {
865    type Item = CompactRefMut<'a, T>;
866    type IntoIter = CompactIterMut<'a, T>;
867    #[inline]
868    fn into_iter(self) -> Self::IntoIter {
869        self.iter_mut()
870    }
871}
872
873/// Owning by-value iterator for [`CompactVec`] (analogous to
874/// `std::vec::IntoIter`).
875pub struct CompactIntoIter<T: CompactRepr> {
876    inner: Store<T>,
877    pos: usize,
878    end: usize,
879}
880
881impl<T: CompactRepr> Iterator for CompactIntoIter<T> {
882    type Item = Compact<T>;
883    #[inline]
884    fn next(&mut self) -> Option<Compact<T>> {
885        if self.pos < self.end {
886            // SAFETY: `pos < end <= len` of the owned storage.
887            let v = Compact(T::decode(unsafe {
888                self.inner.get_unchecked(self.pos)
889            }));
890            self.pos += 1;
891            Some(v)
892        } else {
893            None
894        }
895    }
896    #[inline]
897    fn size_hint(&self) -> (usize, Option<usize>) {
898        let r = self.end - self.pos;
899        (r, Some(r))
900    }
901}
902
903impl<T: CompactRepr> DoubleEndedIterator for CompactIntoIter<T> {
904    #[inline]
905    fn next_back(&mut self) -> Option<Compact<T>> {
906        if self.pos < self.end {
907            self.end -= 1;
908            // SAFETY: as in `next`.
909            Some(Compact(T::decode(unsafe {
910                self.inner.get_unchecked(self.end)
911            })))
912        } else {
913            None
914        }
915    }
916}
917
918impl<T: CompactRepr> ExactSizeIterator for CompactIntoIter<T> {}
919
920impl<T: CompactRepr> IntoIterator for CompactVec<T> {
921    type Item = Compact<T>;
922    type IntoIter = CompactIntoIter<T>;
923    #[inline]
924    fn into_iter(self) -> Self::IntoIter {
925        let end = self.inner.len();
926        CompactIntoIter {
927            inner: self.inner,
928            pos: 0,
929            end,
930        }
931    }
932}
933
934#[cfg(feature = "serde")]
935impl<T: CompactRepr + serde::Serialize> serde::Serialize for CompactVec<T> {
936    fn serialize<S: serde::Serializer>(
937        &self,
938        serializer: S,
939    ) -> Result<S::Ok, S::Error> {
940        use serde::ser::SerializeSeq;
941        let mut seq = serializer.serialize_seq(Some(self.len()))?;
942        for val in self.iter() {
943            seq.serialize_element(&val.0)?;
944        }
945        seq.end()
946    }
947}
948
949#[cfg(feature = "serde")]
950impl<'de, T: CompactRepr + serde::Deserialize<'de>> serde::Deserialize<'de>
951    for CompactVec<T>
952{
953    fn deserialize<D: serde::Deserializer<'de>>(
954        deserializer: D,
955    ) -> Result<Self, D::Error> {
956        use core::fmt;
957
958        use serde::de::{SeqAccess, Visitor};
959
960        struct CompactVecVisitor<T: CompactRepr>(PhantomData<T>);
961        impl<'de, T: CompactRepr + serde::Deserialize<'de>> Visitor<'de>
962            for CompactVecVisitor<T>
963        {
964            type Value = CompactVec<T>;
965            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
966                f.write_str("a sequence of compact values")
967            }
968            fn visit_seq<A: SeqAccess<'de>>(
969                self,
970                mut seq: A,
971            ) -> Result<Self::Value, A::Error> {
972                let mut v = CompactVec::<T>::with_capacity(
973                    seq.size_hint().unwrap_or(0),
974                );
975                while let Some(elem) = seq.next_element::<T>()? {
976                    v.push(Compact(elem));
977                }
978                Ok(v)
979            }
980        }
981        deserializer.deserialize_seq(CompactVecVisitor(PhantomData))
982    }
983}
984
985// ---------------------------------------------------------------------------
986// CompactSlice
987// ---------------------------------------------------------------------------
988
989#[derive(Copy, Clone)]
990pub struct CompactSlice<'a, T: CompactRepr> {
991    // Raw pointer (not a reference) so an empty `Default` slice can hold a
992    // dangling pointer soundly with zero allocation. Reads go through
993    // `unsafe { &*self.packed }` / `(*self.packed)` and are only performed
994    // when `len > 0`, i.e. when the slice is backed by valid storage. The
995    // lifetime is carried by `_marker` (mirrors CompactSliceMut).
996    packed: *const Store<T>,
997    start: usize,
998    len: usize,
999    _marker: PhantomData<&'a Store<T>>,
1000}
1001
1002impl<'a, T: CompactRepr> Default for CompactSlice<'a, T> {
1003    fn default() -> Self {
1004        // Empty slice: `len == 0` guarantees the dangling storage is never
1005        // dereferenced. A dangling raw pointer (not a reference) is sound and
1006        // allocation-free.
1007        CompactSlice {
1008            packed: core::ptr::NonNull::<Store<T>>::dangling().as_ptr(),
1009            start: 0,
1010            len: 0,
1011            _marker: PhantomData,
1012        }
1013    }
1014}
1015
1016#[allow(dead_code)]
1017impl<'a, T: CompactRepr> CompactSlice<'a, T> {
1018    #[inline]
1019    pub fn len(&self) -> usize {
1020        self.len
1021    }
1022
1023    #[inline]
1024    pub fn is_empty(&self) -> bool {
1025        self.len == 0
1026    }
1027
1028    /// Read the element at `offset` from the backing storage.
1029    ///
1030    /// # Safety
1031    ///
1032    /// `offset < self.len` must hold, which also implies the slice is backed
1033    /// by valid storage.
1034    unsafe fn read(&self, offset: usize) -> Compact<T> {
1035        unsafe {
1036            Compact(T::decode(
1037                (*self.packed).get_unchecked(self.start + offset),
1038            ))
1039        }
1040    }
1041
1042    pub fn first(&self) -> Option<Compact<T>> {
1043        if self.is_empty() {
1044            None
1045        } else {
1046            // SAFETY: `0 < self.len`.
1047            Some(unsafe { self.read(0) })
1048        }
1049    }
1050
1051    pub fn last(&self) -> Option<Compact<T>> {
1052        if self.is_empty() {
1053            None
1054        } else {
1055            // SAFETY: `self.len - 1 < self.len`.
1056            Some(unsafe { self.read(self.len - 1) })
1057        }
1058    }
1059
1060    pub fn split_first(&self) -> Option<(Compact<T>, CompactSlice<'a, T>)> {
1061        if self.is_empty() {
1062            return None;
1063        }
1064        Some((
1065            // SAFETY: `0 < self.len`.
1066            unsafe { self.read(0) },
1067            CompactSlice {
1068                packed: self.packed,
1069                start: self.start + 1,
1070                len: self.len - 1,
1071                _marker: PhantomData,
1072            },
1073        ))
1074    }
1075
1076    pub fn split_last(&self) -> Option<(Compact<T>, CompactSlice<'a, T>)> {
1077        if self.is_empty() {
1078            return None;
1079        }
1080        Some((
1081            // SAFETY: `self.len - 1 < self.len`.
1082            unsafe { self.read(self.len - 1) },
1083            CompactSlice {
1084                packed: self.packed,
1085                start: self.start,
1086                len: self.len - 1,
1087                _marker: PhantomData,
1088            },
1089        ))
1090    }
1091
1092    pub fn split_at(
1093        &self,
1094        mid: usize,
1095    ) -> (CompactSlice<'a, T>, CompactSlice<'a, T>) {
1096        assert!(mid <= self.len);
1097        (
1098            CompactSlice {
1099                packed: self.packed,
1100                start: self.start,
1101                len: mid,
1102                _marker: PhantomData,
1103            },
1104            CompactSlice {
1105                packed: self.packed,
1106                start: self.start + mid,
1107                len: self.len - mid,
1108                _marker: PhantomData,
1109            },
1110        )
1111    }
1112
1113    pub fn get(&self, index: usize) -> Option<Compact<T>> {
1114        if index < self.len {
1115            // SAFETY: `index < self.len` just checked.
1116            Some(unsafe { self.read(index) })
1117        } else {
1118            None
1119        }
1120    }
1121
1122    /// Count elements equal to `value` within this slice. Encodes `value` once
1123    /// and counts matching packed lanes (1-bit `T` uses `count_ones`/
1124    /// `count_zeros`).
1125    #[inline]
1126    pub fn count(&self, value: T) -> usize {
1127        if self.len == 0 {
1128            return 0;
1129        }
1130        // SAFETY: `len > 0` implies the slice is backed by valid storage.
1131        unsafe {
1132            (*self.packed).count_in(self.start, self.len, T::encode(value))
1133        }
1134    }
1135
1136    /// Returns the element at `index` without bounds checking.
1137    ///
1138    /// # Safety
1139    ///
1140    /// `index` must be in bounds (`index < self.len`) and the slice must
1141    /// reference initialized backing storage.
1142    pub unsafe fn get_unchecked(&self, index: usize) -> Compact<T> {
1143        // SAFETY: forwarded contract (`index < self.len`).
1144        unsafe { self.read(index) }
1145    }
1146
1147    pub fn index(&self, index: usize) -> Compact<T> {
1148        assert!(
1149            index < self.len,
1150            "index out of bounds: the len is {} but the index is {}",
1151            self.len,
1152            index
1153        );
1154        // SAFETY: `index < self.len` just asserted.
1155        unsafe { self.read(index) }
1156    }
1157
1158    pub fn reborrow<'b>(&'b self) -> CompactSlice<'b, T>
1159    where
1160        'a: 'b,
1161    {
1162        *self
1163    }
1164
1165    pub fn slice(&self, range: Range<usize>) -> CompactSlice<'a, T> {
1166        assert!(range.start <= range.end && range.end <= self.len);
1167        CompactSlice {
1168            packed: self.packed,
1169            start: self.start + range.start,
1170            len: range.end - range.start,
1171            _marker: PhantomData,
1172        }
1173    }
1174
1175    pub fn as_ptr(&self) -> CompactPtr<T> {
1176        CompactPtr {
1177            packed: self.packed as *const Store<T>,
1178            index: self.start,
1179        }
1180    }
1181
1182    /// Reassembles a `CompactSlice` from a raw pointer and length.
1183    ///
1184    /// # Safety
1185    ///
1186    /// `data.packed` must point to valid `Store<T>` storage holding at least
1187    /// `data.index + len` initialized elements, and the returned slice must
1188    /// not outlive that storage.
1189    pub unsafe fn from_raw_parts<'b>(
1190        data: CompactPtr<T>,
1191        len: usize,
1192    ) -> CompactSlice<'b, T> {
1193        CompactSlice {
1194            packed: data.packed,
1195            start: data.index,
1196            len,
1197            _marker: PhantomData,
1198        }
1199    }
1200
1201    pub fn iter(&self) -> CompactIter<'a, T> {
1202        CompactIter::new(self.packed, self.start, self.start + self.len)
1203    }
1204
1205    pub fn to_vec(&self) -> CompactVec<T> {
1206        let mut v = CompactVec::<T>::with_capacity(self.len);
1207        if self.len > 0 {
1208            // SAFETY: `len > 0` implies valid backing storage that does not
1209            // alias the fresh `v`.
1210            v.inner.extend_from_packed(
1211                unsafe { &*self.packed },
1212                self.start,
1213                self.len,
1214            );
1215        }
1216        v
1217    }
1218
1219    pub fn chunks(&self, chunk_size: usize) -> CompactChunks<'a, T> {
1220        assert!(chunk_size != 0, "chunk size must be non-zero");
1221        CompactChunks {
1222            slice: *self,
1223            chunk_size,
1224            pos: 0,
1225        }
1226    }
1227
1228    pub fn chunks_exact(&self, chunk_size: usize) -> CompactChunksExact<'a, T> {
1229        assert!(chunk_size != 0, "chunk size must be non-zero");
1230        let rem = self.len % chunk_size;
1231        CompactChunksExact {
1232            slice: *self,
1233            chunk_size,
1234            pos: 0,
1235            end: self.len - rem,
1236        }
1237    }
1238
1239    pub fn binary_search_by<F>(&self, mut f: F) -> Result<usize, usize>
1240    where
1241        F: FnMut(Compact<T>) -> core::cmp::Ordering,
1242    {
1243        let mut left = 0usize;
1244        let mut right = self.len;
1245        while left < right {
1246            let mid = left + (right - left) / 2;
1247            match f(self.index(mid)) {
1248                core::cmp::Ordering::Less => left = mid + 1,
1249                core::cmp::Ordering::Greater => right = mid,
1250                core::cmp::Ordering::Equal => return Ok(mid),
1251            }
1252        }
1253        Err(left)
1254    }
1255
1256    pub fn binary_search_by_key<K, F>(
1257        &self,
1258        key: &K,
1259        mut f: F,
1260    ) -> Result<usize, usize>
1261    where
1262        K: core::cmp::Ord,
1263        F: FnMut(Compact<T>) -> K,
1264    {
1265        self.binary_search_by(|probe| f(probe).cmp(key))
1266    }
1267}
1268
1269impl<'a, T: CompactRepr> IntoIterator for CompactSlice<'a, T> {
1270    type Item = Compact<T>;
1271    type IntoIter = CompactIter<'a, T>;
1272
1273    #[inline]
1274    fn into_iter(self) -> Self::IntoIter {
1275        self.iter()
1276    }
1277}
1278
1279impl<T: CompactRepr + core::fmt::Debug> core::fmt::Debug
1280    for CompactSlice<'_, T>
1281{
1282    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1283        f.debug_list().entries(self.iter()).finish()
1284    }
1285}
1286
1287impl<'a, T: CompactRepr + PartialEq> PartialEq for CompactSlice<'a, T> {
1288    fn eq(&self, other: &Self) -> bool {
1289        if self.len != other.len {
1290            return false;
1291        }
1292        if self.len == 0 {
1293            return true;
1294        }
1295        // SAFETY: `len > 0` implies both `packed` point at live storage; shared
1296        // reads are fine even when the slices overlap. Word-aligned starts
1297        // compare word-at-a-time.
1298        let a = unsafe { &*self.packed };
1299        let b = unsafe { &*other.packed };
1300        a.range_eq(self.start, b, other.start, self.len)
1301    }
1302}
1303
1304impl<'a, T: CompactRepr + Eq> Eq for CompactSlice<'a, T> {}
1305
1306impl<'a, T: CompactRepr + core::hash::Hash> core::hash::Hash
1307    for CompactSlice<'a, T>
1308{
1309    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1310        self.len.hash(state);
1311        // SAFETY: `packed` is a valid `Store<T>` for the slice's lifetime, and
1312        // `start + i < start + len`.
1313        let a = unsafe { &*self.packed };
1314        for i in 0..self.len {
1315            a.get(self.start + i).hash(state);
1316        }
1317    }
1318}
1319
1320// ---------------------------------------------------------------------------
1321// CompactSliceMut
1322// ---------------------------------------------------------------------------
1323
1324pub struct CompactSliceMut<'a, T: CompactRepr> {
1325    packed: *mut Store<T>,
1326    start: usize,
1327    len: usize,
1328    _marker: PhantomData<&'a mut Store<T>>,
1329}
1330
1331impl<'a, T: CompactRepr> Default for CompactSliceMut<'a, T> {
1332    fn default() -> Self {
1333        CompactSliceMut {
1334            packed: core::ptr::NonNull::<Store<T>>::dangling().as_ptr(),
1335            start: 0,
1336            len: 0,
1337            _marker: PhantomData,
1338        }
1339    }
1340}
1341
1342#[allow(dead_code)]
1343impl<'a, T: CompactRepr> CompactSliceMut<'a, T> {
1344    #[inline]
1345    pub fn len(&self) -> usize {
1346        self.len
1347    }
1348
1349    #[inline]
1350    pub fn is_empty(&self) -> bool {
1351        self.len == 0
1352    }
1353
1354    pub fn as_ref(&self) -> CompactSlice<'_, T> {
1355        CompactSlice {
1356            packed: self.packed as *const Store<T>,
1357            start: self.start,
1358            len: self.len,
1359            _marker: PhantomData,
1360        }
1361    }
1362
1363    pub fn as_slice(&self) -> CompactSlice<'_, T> {
1364        self.as_ref()
1365    }
1366
1367    /// # Safety
1368    ///
1369    /// `offset < self.len` must hold, which also implies the slice is backed
1370    /// by valid storage.
1371    unsafe fn read(&self, offset: usize) -> Compact<T> {
1372        unsafe {
1373            Compact(T::decode(
1374                (*self.packed).get_unchecked(self.start + offset),
1375            ))
1376        }
1377    }
1378
1379    pub fn first_mut(&mut self) -> Option<CompactRefMut<'_, T>> {
1380        if self.is_empty() {
1381            None
1382        } else {
1383            unsafe {
1384                Some(CompactRefMut::from_packed_ptr(self.packed, self.start))
1385            }
1386        }
1387    }
1388
1389    pub fn last_mut(&mut self) -> Option<CompactRefMut<'_, T>> {
1390        if self.is_empty() {
1391            None
1392        } else {
1393            unsafe {
1394                Some(CompactRefMut::from_packed_ptr(
1395                    self.packed,
1396                    self.start + self.len - 1,
1397                ))
1398            }
1399        }
1400    }
1401
1402    pub fn split_first_mut(
1403        self,
1404    ) -> Option<(CompactRefMut<'a, T>, CompactSliceMut<'a, T>)> {
1405        if self.is_empty() {
1406            return None;
1407        }
1408        unsafe {
1409            Some((
1410                CompactRefMut::from_packed_ptr(self.packed, self.start),
1411                CompactSliceMut {
1412                    packed: self.packed,
1413                    start: self.start + 1,
1414                    len: self.len - 1,
1415                    _marker: PhantomData,
1416                },
1417            ))
1418        }
1419    }
1420
1421    pub fn split_last_mut(
1422        self,
1423    ) -> Option<(CompactRefMut<'a, T>, CompactSliceMut<'a, T>)> {
1424        if self.is_empty() {
1425            return None;
1426        }
1427        unsafe {
1428            Some((
1429                CompactRefMut::from_packed_ptr(
1430                    self.packed,
1431                    self.start + self.len - 1,
1432                ),
1433                CompactSliceMut {
1434                    packed: self.packed,
1435                    start: self.start,
1436                    len: self.len - 1,
1437                    _marker: PhantomData,
1438                },
1439            ))
1440        }
1441    }
1442
1443    pub fn split_at_mut(
1444        self,
1445        mid: usize,
1446    ) -> (CompactSliceMut<'a, T>, CompactSliceMut<'a, T>) {
1447        assert!(mid <= self.len);
1448        (
1449            CompactSliceMut {
1450                packed: self.packed,
1451                start: self.start,
1452                len: mid,
1453                _marker: PhantomData,
1454            },
1455            CompactSliceMut {
1456                packed: self.packed,
1457                start: self.start + mid,
1458                len: self.len - mid,
1459                _marker: PhantomData,
1460            },
1461        )
1462    }
1463
1464    pub fn swap(&mut self, a: usize, b: usize) {
1465        assert!(
1466            a < self.len && b < self.len,
1467            "index out of bounds: the len is {} but indices are {} and {}",
1468            self.len,
1469            a,
1470            b
1471        );
1472        // SAFETY: `a < self.len` and `b < self.len` were just asserted, so
1473        // both lanes are in bounds of the live backing storage.
1474        unsafe {
1475            let pa = &mut *self.packed;
1476            let va = pa.get_unchecked(self.start + a);
1477            let vb = pa.get_unchecked(self.start + b);
1478            pa.set_unchecked(self.start + a, vb);
1479            pa.set_unchecked(self.start + b, va);
1480        }
1481    }
1482
1483    pub fn get(&self, index: usize) -> Option<Compact<T>> {
1484        if index < self.len {
1485            unsafe { Some(self.read(index)) }
1486        } else {
1487            None
1488        }
1489    }
1490
1491    /// Returns the element at `index` without bounds checking.
1492    ///
1493    /// # Safety
1494    ///
1495    /// `index` must be in bounds (`index < self.len`) and the slice must
1496    /// reference initialized backing storage.
1497    pub unsafe fn get_unchecked(&self, index: usize) -> Compact<T> {
1498        self.read(index)
1499    }
1500
1501    pub fn index(&self, index: usize) -> Compact<T> {
1502        assert!(
1503            index < self.len,
1504            "index out of bounds: the len is {} but the index is {}",
1505            self.len,
1506            index
1507        );
1508        unsafe { self.read(index) }
1509    }
1510
1511    pub fn get_mut(&mut self, index: usize) -> Option<CompactRefMut<'_, T>> {
1512        if index < self.len {
1513            unsafe {
1514                Some(CompactRefMut::from_packed_ptr(
1515                    self.packed,
1516                    self.start + index,
1517                ))
1518            }
1519        } else {
1520            None
1521        }
1522    }
1523
1524    /// Returns a mutable reference to the element at `index` without bounds
1525    /// checking.
1526    ///
1527    /// # Safety
1528    ///
1529    /// `index` must be in bounds (`index < self.len`), the slice must reference
1530    /// initialized backing storage, and the caller must ensure no other
1531    /// references to the same element exist (no aliasing).
1532    pub unsafe fn get_unchecked_mut(
1533        &mut self,
1534        index: usize,
1535    ) -> CompactRefMut<'_, T> {
1536        CompactRefMut::from_packed_ptr(self.packed, self.start + index)
1537    }
1538
1539    pub fn index_mut(&mut self, index: usize) -> CompactRefMut<'_, T> {
1540        assert!(
1541            index < self.len,
1542            "index out of bounds: the len is {} but the index is {}",
1543            self.len,
1544            index
1545        );
1546        unsafe {
1547            CompactRefMut::from_packed_ptr(self.packed, self.start + index)
1548        }
1549    }
1550
1551    pub fn reborrow<'b>(&'b mut self) -> CompactSliceMut<'b, T>
1552    where
1553        'a: 'b,
1554    {
1555        CompactSliceMut {
1556            packed: self.packed,
1557            start: self.start,
1558            len: self.len,
1559            _marker: PhantomData,
1560        }
1561    }
1562
1563    pub fn slice(&self, range: Range<usize>) -> CompactSlice<'_, T> {
1564        assert!(range.start <= range.end && range.end <= self.len);
1565        CompactSlice {
1566            packed: self.packed as *const Store<T>,
1567            start: self.start + range.start,
1568            len: range.end - range.start,
1569            _marker: PhantomData,
1570        }
1571    }
1572
1573    pub fn as_ptr(&self) -> CompactPtr<T> {
1574        CompactPtr {
1575            packed: self.packed as *const Store<T>,
1576            index: self.start,
1577        }
1578    }
1579
1580    pub fn as_mut_ptr(&mut self) -> CompactPtrMut<T> {
1581        CompactPtrMut {
1582            packed: self.packed,
1583            index: self.start,
1584        }
1585    }
1586
1587    /// Reassembles a `CompactSliceMut` from a raw mutable pointer and length.
1588    ///
1589    /// # Safety
1590    ///
1591    /// `data.packed` must point to valid `Store<T>` storage holding at least
1592    /// `data.index + len` initialized elements, the caller must ensure no
1593    /// other references to that storage exist (unique mutable access), and the
1594    /// returned slice must not outlive the storage.
1595    pub unsafe fn from_raw_parts_mut<'b>(
1596        data: CompactPtrMut<T>,
1597        len: usize,
1598    ) -> CompactSliceMut<'b, T> {
1599        CompactSliceMut {
1600            packed: data.packed,
1601            start: data.index,
1602            len,
1603            _marker: PhantomData,
1604        }
1605    }
1606
1607    pub fn __private_apply_permutation(&mut self, dest: &[usize]) {
1608        let mut visited = crate::__validate_permutation(dest, self.len);
1609        // SAFETY: `dest` was just validated as a permutation of `0..len`.
1610        unsafe {
1611            self.__private_apply_permutation_unchecked(dest, &mut visited)
1612        }
1613    }
1614
1615    /// Apply a destination permutation without re-validating it, reusing the
1616    /// caller's scratch bitmap. Generated composite sorts validate once and
1617    /// then call this per column.
1618    ///
1619    /// # Safety
1620    ///
1621    /// `dest` must be a permutation of `0..self.len()` and `visited` must
1622    /// have been created with capacity for at least `self.len()` bits.
1623    #[doc(hidden)]
1624    pub unsafe fn __private_apply_permutation_unchecked(
1625        &mut self,
1626        dest: &[usize],
1627        visited: &mut crate::VisitedBits,
1628    ) {
1629        let len = self.len;
1630        visited.clear();
1631        // SAFETY: every index in `dest` is `< len` per the caller's
1632        // permutation contract, so `self.start + i` stays within the slice's
1633        // live backing storage.
1634        unsafe {
1635            let pa = &mut *self.packed;
1636            for start in 0..len {
1637                if visited.test(start) {
1638                    continue;
1639                }
1640                // `dest` maps each current index to its destination index.
1641                // Rotate each cycle into place using a single saved value so no
1642                // element is lost.
1643                visited.set(start);
1644                let mut temp = pa.get_unchecked(self.start + start);
1645                let mut current = start;
1646                loop {
1647                    let next = *dest.get_unchecked(current);
1648                    if next == start {
1649                        pa.set_unchecked(self.start + start, temp);
1650                        break;
1651                    }
1652                    let saved = pa.get_unchecked(self.start + next);
1653                    pa.set_unchecked(self.start + next, temp);
1654                    temp = saved;
1655                    visited.set(next);
1656                    current = next;
1657                }
1658            }
1659        }
1660    }
1661
1662    pub fn iter(&self) -> CompactIter<'_, T> {
1663        CompactIter::new(
1664            self.packed as *const Store<T>,
1665            self.start,
1666            self.start + self.len,
1667        )
1668    }
1669
1670    pub fn iter_mut(&mut self) -> CompactIterMut<'_, T> {
1671        CompactIterMut {
1672            packed: self.packed,
1673            pos: self.start,
1674            end: self.start + self.len,
1675            _marker: PhantomData,
1676        }
1677    }
1678
1679    pub fn to_vec(&self) -> CompactVec<T> {
1680        self.as_ref().to_vec()
1681    }
1682
1683    pub fn chunks_mut<'b>(
1684        &'b mut self,
1685        chunk_size: usize,
1686    ) -> CompactChunksMut<'b, T>
1687    where
1688        'a: 'b,
1689    {
1690        assert!(chunk_size != 0, "chunk size must be non-zero");
1691        CompactChunksMut {
1692            packed: self.packed,
1693            start: self.start,
1694            len: self.len,
1695            chunk_size,
1696            pos: 0,
1697            _marker: PhantomData,
1698        }
1699    }
1700
1701    pub fn chunks_exact_mut<'b>(
1702        &'b mut self,
1703        chunk_size: usize,
1704    ) -> CompactChunksExactMut<'b, T>
1705    where
1706        'a: 'b,
1707    {
1708        assert!(chunk_size != 0, "chunk size must be non-zero");
1709        let rem = self.len % chunk_size;
1710        CompactChunksExactMut {
1711            packed: self.packed,
1712            start: self.start,
1713            len: self.len,
1714            chunk_size,
1715            pos: 0,
1716            end: self.len - rem,
1717            _marker: PhantomData,
1718        }
1719    }
1720
1721    /// Sort the slice with a comparator.
1722    ///
1723    /// A compact column holds at most `2^BITS <= 16` distinct values, so this
1724    /// is a counting sort: the raw lane values are counted in one word-level
1725    /// pass, the distinct values are ordered with `f`, and the slice is
1726    /// rewritten with word-level fills. Consequences (all documented
1727    /// contract):
1728    ///
1729    /// * `f` is invoked on distinct values only (at most 120 calls), never once
1730    ///   per element, so it must be a pure comparison.
1731    /// * Elements whose values compare `Equal` are grouped by their stored
1732    ///   value (the observable result of `slice::sort_unstable_by`), not
1733    ///   interleaved in their original order.
1734    ///
1735    /// Runs in `O(n / lanes_per_word)` word operations with no allocation.
1736    pub fn sort_by<F>(&mut self, mut f: F)
1737    where
1738        F: FnMut(Compact<T>, Compact<T>) -> core::cmp::Ordering,
1739    {
1740        let len = self.len;
1741        if len <= 1 {
1742            return;
1743        }
1744        let nvals = 1usize << T::BITS;
1745        debug_assert!(nvals <= 16);
1746        // Count every raw lane value. The last bucket comes from the length,
1747        // so a 1-bit column costs a single `count_ones` pass.
1748        let mut counts = [0usize; 16];
1749        {
1750            // SAFETY: the slice's lanes are within the live store.
1751            let pa = unsafe { &*self.packed };
1752            let mut seen = 0;
1753            for (v, slot) in counts.iter_mut().enumerate().take(nvals - 1) {
1754                let c = pa.count_in(self.start, len, v);
1755                *slot = c;
1756                seen += c;
1757            }
1758            counts[nvals - 1] = len - seen;
1759        }
1760        // Order the value table with `f` (stable insertion sort of at most 16
1761        // entries, so equal-comparing values keep ascending raw order).
1762        let mut order = [0usize; 16];
1763        for (v, slot) in order.iter_mut().enumerate().take(nvals) {
1764            *slot = v;
1765        }
1766        for i in 1..nvals {
1767            let mut j = i;
1768            while j > 0
1769                && f(
1770                    Compact(T::decode(order[j - 1])),
1771                    Compact(T::decode(order[j])),
1772                ) == core::cmp::Ordering::Greater
1773            {
1774                order.swap(j - 1, j);
1775                j -= 1;
1776            }
1777        }
1778        // Rewrite the slice as runs of equal values, word-level.
1779        // SAFETY: the slice's lanes are within the live store; the runs sum
1780        // to exactly `len`.
1781        let pa = unsafe { &mut *self.packed };
1782        let mut at = self.start;
1783        for &v in order.iter().take(nvals) {
1784            let c = counts[v];
1785            if c > 0 {
1786                pa.fill_range(at, c, v);
1787                at += c;
1788            }
1789        }
1790    }
1791
1792    /// Sort the slice by a key function.
1793    ///
1794    /// Counting sort, like [`sort_by`](Self::sort_by): the key function is
1795    /// invoked on distinct values only (at most 240 calls), and elements
1796    /// whose keys compare equal are grouped by their stored value.
1797    pub fn sort_by_key<F, K>(&mut self, mut f: F)
1798    where
1799        F: FnMut(Compact<T>) -> K,
1800        K: Ord,
1801    {
1802        self.sort_by(|a, b| f(a).cmp(&f(b)));
1803    }
1804
1805    /// Sort the slice by `T`'s ordering (counting sort, see
1806    /// [`sort_by`](Self::sort_by)).
1807    pub fn sort(&mut self)
1808    where
1809        T: Ord,
1810    {
1811        self.sort_by(|a, b| a.0.cmp(&b.0));
1812    }
1813}
1814
1815impl<'a, T: CompactRepr> IntoIterator for CompactSliceMut<'a, T> {
1816    type Item = CompactRefMut<'a, T>;
1817    type IntoIter = CompactIterMut<'a, T>;
1818
1819    #[inline]
1820    fn into_iter(self) -> Self::IntoIter {
1821        CompactIterMut {
1822            packed: self.packed,
1823            pos: self.start,
1824            end: self.start + self.len,
1825            _marker: PhantomData,
1826        }
1827    }
1828}
1829
1830impl<T: CompactRepr + core::fmt::Debug> core::fmt::Debug
1831    for CompactSliceMut<'_, T>
1832{
1833    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1834        f.debug_list().entries(self.iter()).finish()
1835    }
1836}
1837
1838impl<'a, T: CompactRepr + PartialEq> PartialEq for CompactSliceMut<'a, T> {
1839    fn eq(&self, other: &Self) -> bool {
1840        if self.len != other.len {
1841            return false;
1842        }
1843        if self.len == 0 {
1844            return true;
1845        }
1846        // SAFETY: `len > 0` implies both `packed` point at live storage; `eq`
1847        // only reads, so shared refs are fine even though the pointers are
1848        // `*mut`. Word-aligned starts compare word-at-a-time.
1849        let a = unsafe { &*self.packed };
1850        let b = unsafe { &*other.packed };
1851        a.range_eq(self.start, b, other.start, self.len)
1852    }
1853}
1854
1855impl<'a, T: CompactRepr + Eq> Eq for CompactSliceMut<'a, T> {}
1856
1857impl<'a, T: CompactRepr + core::hash::Hash> core::hash::Hash
1858    for CompactSliceMut<'a, T>
1859{
1860    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1861        self.len.hash(state);
1862        // SAFETY: `packed` is a valid `Store<T>` for the slice's lifetime, and
1863        // `start + i < start + len`.
1864        let a = unsafe { &*self.packed };
1865        for i in 0..self.len {
1866            a.get(self.start + i).hash(state);
1867        }
1868    }
1869}
1870
1871// ---------------------------------------------------------------------------
1872// CompactPtr / CompactPtrMut. A pointer is either storage-backed (`packed`
1873// points to a column, `index` addresses the element) or direct (`packed`
1874// holds a pointer to a standalone `Compact<T>` value, e.g. the compact
1875// field of a `Ref`/`RefMut` or an owned value, and `index` is
1876// `DIRECT_INDEX`). Direct pointers keep element pointers derived from a
1877// `Ref`/`RefMut` non-null and usable instead of collapsing them to null.
1878// The sentinel keeps the layout at two words and leaves every
1879// storage-backed code path unchanged. `CompactPtr::as_mut_ptr` is the one
1880// exception: a direct CONST pointer borrows immutably, so there is no
1881// storage a write could legally target and it converts to null.
1882// ---------------------------------------------------------------------------
1883
1884/// `index` sentinel marking a direct `CompactPtr`. A storage-backed index can
1885/// never reach `usize::MAX` (no allocation can hold that many elements), so
1886/// the two modes cannot collide.
1887const DIRECT_INDEX: usize = usize::MAX;
1888
1889#[derive(Copy, Clone)]
1890pub struct CompactPtr<T: CompactRepr> {
1891    packed: *const Store<T>,
1892    index: usize,
1893}
1894
1895#[derive(Copy, Clone)]
1896pub struct CompactPtrMut<T: CompactRepr> {
1897    packed: *mut Store<T>,
1898    index: usize,
1899}
1900
1901// Pointer-like: Debug/PartialEq/Eq/Hash over (packed address, index), matching
1902// raw pointers (no `T` bound needed). This lets `#[layout(Debug/PartialEq/Eq/
1903// Hash)]` derive on the generated Ptr/PtrMut types compile for compact columns.
1904impl<T: CompactRepr> core::fmt::Debug for CompactPtr<T> {
1905    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1906        f.debug_struct("CompactPtr")
1907            .field("packed", &self.packed)
1908            .field("index", &self.index)
1909            .finish()
1910    }
1911}
1912
1913impl<T: CompactRepr> PartialEq for CompactPtr<T> {
1914    fn eq(&self, other: &Self) -> bool {
1915        self.packed == other.packed && self.index == other.index
1916    }
1917}
1918
1919impl<T: CompactRepr> Eq for CompactPtr<T> {}
1920
1921impl<T: CompactRepr> core::hash::Hash for CompactPtr<T> {
1922    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1923        self.packed.hash(state);
1924        self.index.hash(state);
1925    }
1926}
1927
1928impl<T: CompactRepr> core::fmt::Debug for CompactPtrMut<T> {
1929    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1930        f.debug_struct("CompactPtrMut")
1931            .field("packed", &self.packed)
1932            .field("index", &self.index)
1933            .finish()
1934    }
1935}
1936
1937impl<T: CompactRepr> PartialEq for CompactPtrMut<T> {
1938    fn eq(&self, other: &Self) -> bool {
1939        self.packed == other.packed && self.index == other.index
1940    }
1941}
1942
1943impl<T: CompactRepr> Eq for CompactPtrMut<T> {}
1944
1945impl<T: CompactRepr> core::hash::Hash for CompactPtrMut<T> {
1946    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1947        self.packed.hash(state);
1948        self.index.hash(state);
1949    }
1950}
1951
1952#[allow(dead_code)]
1953impl<T: CompactRepr> CompactPtr<T> {
1954    pub fn is_null(self) -> bool {
1955        self.packed.is_null()
1956    }
1957
1958    /// Returns the element the pointer references, or `None` if it is null.
1959    ///
1960    /// # Safety
1961    ///
1962    /// If non-null, `self.packed` must point to valid `Store<T>` storage
1963    /// (or, for a direct pointer, to a live `T`) and `self.index` must
1964    /// address an initialized element within it. The caller must ensure the
1965    /// backing storage remains live while the returned value is used.
1966    pub unsafe fn as_ref(self) -> Option<Compact<T>> {
1967        if self.is_null() {
1968            None
1969        } else if self.index == DIRECT_INDEX {
1970            Some(Compact(*self.packed.cast::<T>()))
1971        } else {
1972            // SAFETY: the caller guarantees `index` addresses an initialized
1973            // element of the live storage.
1974            Some(Compact(T::decode((*self.packed).get_unchecked(self.index))))
1975        }
1976    }
1977
1978    /// Direct pointers convert to a null mutable pointer: they borrow a
1979    /// standalone value immutably, so there is no storage a write could
1980    /// legally target.
1981    pub fn as_mut_ptr(&self) -> CompactPtrMut<T> {
1982        if self.index == DIRECT_INDEX {
1983            CompactPtrMut {
1984                packed: core::ptr::null_mut(),
1985                index: 0,
1986            }
1987        } else {
1988            CompactPtrMut {
1989                packed: self.packed as *mut Store<T>,
1990                index: self.index,
1991            }
1992        }
1993    }
1994
1995    /// Produces a pointer offset by `count` elements (analogous to
1996    /// [`pointer::offset`](core::pointer::offset)).
1997    ///
1998    /// # Safety
1999    ///
2000    /// The resulting index (`self.index + count`) must be in bounds or one
2001    /// past the end of the same allocated backing storage.
2002    pub unsafe fn offset(self, count: isize) -> CompactPtr<T> {
2003        CompactPtr {
2004            packed: self.packed,
2005            index: (self.index as isize + count) as usize,
2006        }
2007    }
2008
2009    /// Produces a pointer advanced by `count` elements (analogous to
2010    /// [`pointer::add`](core::pointer::add)).
2011    ///
2012    /// # Safety
2013    ///
2014    /// The resulting index (`self.index + count`) must be in bounds or one
2015    /// past the end of the same allocated backing storage.
2016    pub unsafe fn add(self, count: usize) -> CompactPtr<T> {
2017        CompactPtr {
2018            packed: self.packed,
2019            index: self.index + count,
2020        }
2021    }
2022
2023    /// Produces a pointer moved back by `count` elements (analogous to
2024    /// [`pointer::sub`](core::pointer::sub)).
2025    ///
2026    /// # Safety
2027    ///
2028    /// `count` must not exceed `self.index`; the resulting index must be in
2029    /// bounds of the same allocated backing storage.
2030    pub unsafe fn sub(self, count: usize) -> CompactPtr<T> {
2031        CompactPtr {
2032            packed: self.packed,
2033            index: self.index - count,
2034        }
2035    }
2036
2037    /// Reads the element the pointer references (analogous to
2038    /// [`pointer::read`](core::pointer::read)).
2039    ///
2040    /// # Safety
2041    ///
2042    /// `self.packed` must point to valid `Store<T>` storage (or, for a
2043    /// direct pointer, to a live `T`) and `self.index` must address an
2044    /// initialized element within it.
2045    pub unsafe fn read(self) -> Compact<T> {
2046        if self.index == DIRECT_INDEX {
2047            Compact(*self.packed.cast::<T>())
2048        } else {
2049            // SAFETY: the caller guarantees `index` addresses an initialized
2050            // element of the live storage.
2051            Compact(T::decode((*self.packed).get_unchecked(self.index)))
2052        }
2053    }
2054}
2055
2056#[allow(dead_code)]
2057impl<T: CompactRepr> CompactPtrMut<T> {
2058    pub fn is_null(self) -> bool {
2059        self.packed.is_null()
2060    }
2061
2062    /// Returns the element the pointer references, or `None` if it is null.
2063    ///
2064    /// # Safety
2065    ///
2066    /// If non-null, `self.packed` must point to valid `Store<T>` storage and
2067    /// `self.index` must address an initialized element within it.
2068    pub unsafe fn as_ref(self) -> Option<Compact<T>> {
2069        if self.is_null() {
2070            None
2071        } else if self.index == DIRECT_INDEX {
2072            // SAFETY: a direct pointer disguises a live `*mut T`.
2073            Some(Compact(*self.packed.cast::<T>()))
2074        } else {
2075            // SAFETY: the caller guarantees `index` addresses an initialized
2076            // element of the live storage.
2077            Some(Compact(T::decode((*self.packed).get_unchecked(self.index))))
2078        }
2079    }
2080
2081    /// Returns a mutable reference to the element the pointer references, or
2082    /// `None` if it is null.
2083    ///
2084    /// # Safety
2085    ///
2086    /// If non-null, `self.packed` must point to valid `Store<T>` storage (or,
2087    /// for a direct pointer, to a live `T`), `self.index` must address an
2088    /// initialized element within it, and the caller must ensure no other
2089    /// references to the same element exist (no aliasing).
2090    pub unsafe fn as_mut<'a>(self) -> Option<CompactRefMut<'a, T>> {
2091        if self.is_null() {
2092            None
2093        } else {
2094            // Identical representation: the direct sentinel carries over.
2095            Some(CompactRefMut::from_packed_ptr(self.packed, self.index))
2096        }
2097    }
2098
2099    pub fn as_ptr(&self) -> CompactPtr<T> {
2100        CompactPtr {
2101            packed: self.packed,
2102            index: self.index,
2103        }
2104    }
2105
2106    /// Produces a pointer offset by `count` elements (analogous to
2107    /// [`pointer::offset`](core::pointer::offset)).
2108    ///
2109    /// # Safety
2110    ///
2111    /// The resulting index (`self.index + count`) must be in bounds or one
2112    /// past the end of the same allocated backing storage.
2113    pub unsafe fn offset(self, count: isize) -> CompactPtrMut<T> {
2114        CompactPtrMut {
2115            packed: self.packed,
2116            index: (self.index as isize + count) as usize,
2117        }
2118    }
2119
2120    /// Produces a pointer advanced by `count` elements (analogous to
2121    /// [`pointer::add`](core::pointer::add)).
2122    ///
2123    /// # Safety
2124    ///
2125    /// The resulting index (`self.index + count`) must be in bounds or one
2126    /// past the end of the same allocated backing storage.
2127    pub unsafe fn add(self, count: usize) -> CompactPtrMut<T> {
2128        CompactPtrMut {
2129            packed: self.packed,
2130            index: self.index + count,
2131        }
2132    }
2133
2134    /// Produces a pointer moved back by `count` elements (analogous to
2135    /// [`pointer::sub`](core::pointer::sub)).
2136    ///
2137    /// # Safety
2138    ///
2139    /// `count` must not exceed `self.index`; the resulting index must be in
2140    /// bounds of the same allocated backing storage.
2141    pub unsafe fn sub(self, count: usize) -> CompactPtrMut<T> {
2142        CompactPtrMut {
2143            packed: self.packed,
2144            index: self.index - count,
2145        }
2146    }
2147
2148    /// Reads the element the pointer references (analogous to
2149    /// [`pointer::read`](core::pointer::read)).
2150    ///
2151    /// # Safety
2152    ///
2153    /// `self.packed` must point to valid `Store<T>` storage and `self.index`
2154    /// must address an initialized element within it.
2155    pub unsafe fn read(self) -> Compact<T> {
2156        if self.index == DIRECT_INDEX {
2157            // SAFETY: a direct pointer disguises a live `*mut T`.
2158            Compact(*self.packed.cast::<T>())
2159        } else {
2160            // SAFETY: the caller guarantees `index` addresses an initialized
2161            // element of the live storage.
2162            Compact(T::decode((*self.packed).get_unchecked(self.index)))
2163        }
2164    }
2165
2166    /// Overwrites the element the pointer references (analogous to
2167    /// [`pointer::write`](core::pointer::write)).
2168    ///
2169    /// # Safety
2170    ///
2171    /// `self.packed` must point to valid `Store<T>` storage (or, for a direct
2172    /// pointer, to a live, writable `T`), `self.index` must address a
2173    /// writable element within it, and the caller must ensure no other
2174    /// references to the same element exist (no aliasing).
2175    #[allow(clippy::forget_non_drop)]
2176    pub unsafe fn write(self, val: Compact<T>) {
2177        if self.index == DIRECT_INDEX {
2178            // SAFETY: a direct pointer disguises a live, writable `*mut T`.
2179            *self.packed.cast::<T>() = val.0;
2180        } else {
2181            // SAFETY: the caller guarantees `index` addresses a writable
2182            // element of the live storage.
2183            (*self.packed).set_unchecked(self.index, T::encode(val.0));
2184        }
2185    }
2186}
2187
2188// ---------------------------------------------------------------------------
2189// CompactIter / CompactIterMut
2190// ---------------------------------------------------------------------------
2191
2192pub struct CompactIter<'a, T: CompactRepr> {
2193    packed: *const Store<T>,
2194    pos: usize,
2195    end: usize,
2196    // Forward read cache: the current word pre-shifted so the lane at `pos`
2197    // sits in the low `BITS` bits, with `avail` lanes left in it (0 forces a
2198    // reload). Each forward step is then one mask and one constant shift;
2199    // memory is touched once per word. Sound because the iterator holds a
2200    // shared borrow, so the storage cannot change. Back reads go straight to
2201    // memory and leave the cache alone.
2202    cur_word: usize,
2203    avail: usize,
2204    _marker: PhantomData<&'a Store<T>>,
2205}
2206
2207impl<'a, T: CompactRepr> CompactIter<'a, T> {
2208    #[inline]
2209    fn new(packed: *const Store<T>, pos: usize, end: usize) -> Self {
2210        Self {
2211            packed,
2212            pos,
2213            end,
2214            cur_word: 0,
2215            avail: 0,
2216            _marker: PhantomData,
2217        }
2218    }
2219
2220    /// Read the lane at `pos` and advance, reloading the shifted word cache
2221    /// at word boundaries.
2222    ///
2223    /// # Safety
2224    ///
2225    /// `pos < end` must hold (the lane is within the live storage).
2226    #[inline(always)]
2227    unsafe fn read_front(&mut self) -> Compact<T> {
2228        let per = (usize::BITS / T::BITS) as usize;
2229        if self.avail == 0 {
2230            let off = self.pos % per;
2231            // SAFETY: `pos < end <= len`, so the word is live.
2232            self.cur_word = unsafe { (*self.packed).word(self.pos / per) }
2233                >> (off * T::BITS as usize);
2234            self.avail = per - off;
2235        }
2236        let raw = self.cur_word & ((1usize << T::BITS) - 1);
2237        self.cur_word >>= T::BITS;
2238        self.avail -= 1;
2239        self.pos += 1;
2240        Compact(T::decode(raw))
2241    }
2242
2243    /// Step the back end down and read that lane directly (uncached).
2244    ///
2245    /// # Safety
2246    ///
2247    /// `pos < end` must hold.
2248    #[inline]
2249    unsafe fn read_back(&mut self) -> Compact<T> {
2250        self.end -= 1;
2251        let per = (usize::BITS / T::BITS) as usize;
2252        let off = (self.end % per) * T::BITS as usize;
2253        // SAFETY: `end` was within the live storage.
2254        let word = unsafe { (*self.packed).word(self.end / per) };
2255        Compact(T::decode((word >> off) & ((1usize << T::BITS) - 1)))
2256    }
2257}
2258
2259impl<'a, T: CompactRepr> Iterator for CompactIter<'a, T> {
2260    type Item = Compact<T>;
2261    #[inline]
2262    fn next(&mut self) -> Option<Compact<T>> {
2263        if self.pos < self.end {
2264            // SAFETY: `pos < end` just checked.
2265            Some(unsafe { self.read_front() })
2266        } else {
2267            None
2268        }
2269    }
2270    #[inline]
2271    fn size_hint(&self) -> (usize, Option<usize>) {
2272        let r = self.end - self.pos;
2273        (r, Some(r))
2274    }
2275    #[inline]
2276    fn count(self) -> usize {
2277        self.end - self.pos
2278    }
2279    #[inline]
2280    fn nth(&mut self, n: usize) -> Option<Compact<T>> {
2281        let remaining = self.end - self.pos;
2282        if n >= remaining {
2283            self.pos = self.end;
2284            self.avail = 0;
2285            return None;
2286        }
2287        // Jump the cursor and invalidate the shifted word cache.
2288        self.pos += n;
2289        self.avail = 0;
2290        self.next()
2291    }
2292    #[inline]
2293    fn last(mut self) -> Option<Compact<T>> {
2294        if self.pos < self.end {
2295            // SAFETY: `pos < end` just checked.
2296            Some(unsafe { self.read_back() })
2297        } else {
2298            None
2299        }
2300    }
2301    fn fold<B, F>(mut self, init: B, mut f: F) -> B
2302    where
2303        F: FnMut(B, Compact<T>) -> B,
2304    {
2305        // Internal iteration goes word-at-a-time: each backing word is
2306        // loaded once and its lanes are peeled with constant shifts, with no
2307        // per-element cursor bookkeeping. This is what `for_each`, `count`
2308        // after `filter`, `sum` and friends compile down to.
2309        let mut acc = init;
2310        let per = (usize::BITS / T::BITS) as usize;
2311        let mask = (1usize << T::BITS) - 1;
2312        while self.pos < self.end {
2313            let off = self.pos % per;
2314            let in_word = (per - off).min(self.end - self.pos);
2315            // SAFETY: `pos < end <= len`, so the word is live.
2316            let mut w = unsafe { (*self.packed).word(self.pos / per) }
2317                >> (off * T::BITS as usize);
2318            for _ in 0..in_word {
2319                acc = f(acc, Compact(T::decode(w & mask)));
2320                w >>= T::BITS;
2321            }
2322            self.pos += in_word;
2323        }
2324        acc
2325    }
2326}
2327
2328impl<'a, T: CompactRepr> DoubleEndedIterator for CompactIter<'a, T> {
2329    #[inline]
2330    fn next_back(&mut self) -> Option<Compact<T>> {
2331        if self.pos < self.end {
2332            // SAFETY: `pos < end` just checked.
2333            Some(unsafe { self.read_back() })
2334        } else {
2335            None
2336        }
2337    }
2338}
2339
2340impl<T: CompactRepr> ExactSizeIterator for CompactIter<'_, T> {}
2341
2342impl<'a, T: CompactRepr> crate::SoACursor for CompactIter<'a, T> {
2343    type Item = Compact<T>;
2344    #[inline(always)]
2345    unsafe fn cursor_next(&mut self) -> Compact<T> {
2346        // SAFETY: the caller's length contract replaces the `pos < end`
2347        // check.
2348        unsafe { self.read_front() }
2349    }
2350    #[inline(always)]
2351    unsafe fn cursor_next_back(&mut self) -> Compact<T> {
2352        // SAFETY: as in `cursor_next`.
2353        unsafe { self.read_back() }
2354    }
2355}
2356
2357pub struct CompactIterMut<'a, T: CompactRepr> {
2358    packed: *mut Store<T>,
2359    pos: usize,
2360    end: usize,
2361    _marker: PhantomData<&'a mut Store<T>>,
2362}
2363
2364impl<'a, T: CompactRepr> Iterator for CompactIterMut<'a, T> {
2365    type Item = CompactRefMut<'a, T>;
2366    #[inline]
2367    fn next(&mut self) -> Option<CompactRefMut<'a, T>> {
2368        if self.pos < self.end {
2369            let i = self.pos;
2370            self.pos += 1;
2371            // SAFETY: `i` is in `[pos, end)` ⊆ `[0, len)` of the live storage.
2372            Some(unsafe { CompactRefMut::from_packed_ptr(self.packed, i) })
2373        } else {
2374            None
2375        }
2376    }
2377    #[inline]
2378    fn size_hint(&self) -> (usize, Option<usize>) {
2379        let r = self.end - self.pos;
2380        (r, Some(r))
2381    }
2382}
2383
2384impl<'a, T: CompactRepr> DoubleEndedIterator for CompactIterMut<'a, T> {
2385    #[inline]
2386    fn next_back(&mut self) -> Option<CompactRefMut<'a, T>> {
2387        if self.pos < self.end {
2388            self.end -= 1;
2389            // SAFETY: `end` is in `[pos, end)` ⊆ `[0, len)` of the live
2390            // storage.
2391            Some(unsafe {
2392                CompactRefMut::from_packed_ptr(self.packed, self.end)
2393            })
2394        } else {
2395            None
2396        }
2397    }
2398}
2399
2400impl<T: CompactRepr> ExactSizeIterator for CompactIterMut<'_, T> {}
2401
2402impl<'a, T: CompactRepr> crate::SoACursor for CompactIterMut<'a, T> {
2403    type Item = CompactRefMut<'a, T>;
2404    #[inline(always)]
2405    unsafe fn cursor_next(&mut self) -> CompactRefMut<'a, T> {
2406        let i = self.pos;
2407        self.pos += 1;
2408        // SAFETY: the caller's length contract keeps `i` within the
2409        // iterator's range of the live storage.
2410        unsafe { CompactRefMut::from_packed_ptr(self.packed, i) }
2411    }
2412    #[inline(always)]
2413    unsafe fn cursor_next_back(&mut self) -> CompactRefMut<'a, T> {
2414        self.end -= 1;
2415        // SAFETY: as in `cursor_next`.
2416        unsafe { CompactRefMut::from_packed_ptr(self.packed, self.end) }
2417    }
2418}
2419
2420// ---------------------------------------------------------------------------
2421// CompactDrain
2422// ---------------------------------------------------------------------------
2423
2424pub struct CompactDrain<'a, T: CompactRepr> {
2425    // The store's logical length was lowered to `drain_start` when the drain
2426    // was created (leak safety), but every lane `< old_len` stays alive in
2427    // the backing words until `Drop` shifts the tail and truncates.
2428    packed: &'a mut Store<T>,
2429    // Original drain window; used by `Drop` to shift the tail regardless of
2430    // how many elements were yielded by the iterator.
2431    drain_start: usize,
2432    drain_end: usize,
2433    // Pre-drain length of the store.
2434    old_len: usize,
2435    // Live iteration cursors.
2436    pos: usize,
2437    back: usize,
2438}
2439
2440impl<T: CompactRepr> Iterator for CompactDrain<'_, T> {
2441    type Item = Compact<T>;
2442    #[inline]
2443    fn next(&mut self) -> Option<Compact<T>> {
2444        if self.pos < self.back {
2445            // SAFETY: `pos < back <= drain_end <= old_len`; the lane is
2446            // initialized and its word stays alive for the drain's lifetime
2447            // even though it sits beyond the store's lowered length.
2448            let v = Compact(T::decode(unsafe {
2449                self.packed.get_unchecked(self.pos)
2450            }));
2451            self.pos += 1;
2452            Some(v)
2453        } else {
2454            None
2455        }
2456    }
2457    #[inline]
2458    fn size_hint(&self) -> (usize, Option<usize>) {
2459        let r = self.back - self.pos;
2460        (r, Some(r))
2461    }
2462}
2463
2464impl<T: CompactRepr> DoubleEndedIterator for CompactDrain<'_, T> {
2465    #[inline]
2466    fn next_back(&mut self) -> Option<Compact<T>> {
2467        if self.pos < self.back {
2468            self.back -= 1;
2469            // SAFETY: as in `next`.
2470            Some(Compact(T::decode(unsafe {
2471                self.packed.get_unchecked(self.back)
2472            })))
2473        } else {
2474            None
2475        }
2476    }
2477}
2478
2479impl<T: CompactRepr> ExactSizeIterator for CompactDrain<'_, T> {}
2480
2481impl<T: CompactRepr> Drop for CompactDrain<'_, T> {
2482    fn drop(&mut self) {
2483        // Restore the pre-drain length, shift the tail [drain_end, old_len)
2484        // down to [drain_start, ...), then truncate to the final length.
2485        // Uses the ORIGINAL window so this runs even after the iterator was
2486        // fully (or partially) consumed; `truncate` also re-tightens the
2487        // backing words.
2488        let drain_len = self.drain_end - self.drain_start;
2489        let tail = self.old_len - self.drain_end;
2490        // SAFETY: every lane `< old_len` is initialized and its word stayed
2491        // alive while the length was lowered (`set_len` never trims words).
2492        unsafe {
2493            self.packed.set_len(self.old_len);
2494        }
2495        if drain_len > 0 {
2496            // Word-level tail shift over the drained gap.
2497            self.packed
2498                .copy_lanes(self.drain_end, self.drain_start, tail);
2499        }
2500        self.packed.truncate(self.old_len - drain_len);
2501    }
2502}
2503
2504// ---------------------------------------------------------------------------
2505// Chunk iterators
2506// ---------------------------------------------------------------------------
2507
2508pub struct CompactChunks<'a, T: CompactRepr> {
2509    slice: CompactSlice<'a, T>,
2510    chunk_size: usize,
2511    pos: usize,
2512}
2513
2514impl<'a, T: CompactRepr> Iterator for CompactChunks<'a, T> {
2515    type Item = CompactSlice<'a, T>;
2516    #[inline]
2517    fn next(&mut self) -> Option<CompactSlice<'a, T>> {
2518        if self.pos >= self.slice.len || self.chunk_size == 0 {
2519            return None;
2520        }
2521        let end = (self.pos + self.chunk_size).min(self.slice.len);
2522        let result = CompactSlice {
2523            packed: self.slice.packed,
2524            start: self.slice.start + self.pos,
2525            len: end - self.pos,
2526            _marker: PhantomData,
2527        };
2528        self.pos = end;
2529        Some(result)
2530    }
2531    #[inline]
2532    fn size_hint(&self) -> (usize, Option<usize>) {
2533        if self.chunk_size == 0 {
2534            return (0, Some(0));
2535        }
2536        // Non-overflowing ceiling division (`r + chunk_size` can wrap for a
2537        // huge chunk size).
2538        let r = self.slice.len.saturating_sub(self.pos);
2539        let c = r / self.chunk_size + usize::from(r % self.chunk_size != 0);
2540        (c, Some(c))
2541    }
2542    #[inline]
2543    fn count(self) -> usize {
2544        self.size_hint().0
2545    }
2546}
2547
2548impl<T: CompactRepr> ExactSizeIterator for CompactChunks<'_, T> {}
2549
2550pub struct CompactChunksExact<'a, T: CompactRepr> {
2551    slice: CompactSlice<'a, T>,
2552    chunk_size: usize,
2553    pos: usize,
2554    end: usize,
2555}
2556
2557impl<'a, T: CompactRepr> Iterator for CompactChunksExact<'a, T> {
2558    type Item = CompactSlice<'a, T>;
2559    #[inline]
2560    fn next(&mut self) -> Option<CompactSlice<'a, T>> {
2561        if self.pos >= self.end || self.chunk_size == 0 {
2562            return None;
2563        }
2564        let result = CompactSlice {
2565            packed: self.slice.packed,
2566            start: self.slice.start + self.pos,
2567            len: self.chunk_size,
2568            _marker: PhantomData,
2569        };
2570        self.pos += self.chunk_size;
2571        Some(result)
2572    }
2573    #[inline]
2574    fn size_hint(&self) -> (usize, Option<usize>) {
2575        if self.chunk_size == 0 {
2576            return (0, Some(0));
2577        }
2578        let r = self.end.saturating_sub(self.pos);
2579        let c = r / self.chunk_size;
2580        (c, Some(c))
2581    }
2582    #[inline]
2583    fn count(self) -> usize {
2584        self.size_hint().0
2585    }
2586}
2587
2588impl<T: CompactRepr> ExactSizeIterator for CompactChunksExact<'_, T> {}
2589
2590#[allow(dead_code)]
2591impl<'a, T: CompactRepr> CompactChunksExact<'a, T> {
2592    pub fn remainder(&self) -> CompactSlice<'a, T> {
2593        let rem_start = self.end.min(self.slice.len);
2594        CompactSlice {
2595            packed: self.slice.packed,
2596            start: self.slice.start + rem_start,
2597            len: self.slice.len - rem_start,
2598            _marker: PhantomData,
2599        }
2600    }
2601}
2602
2603pub struct CompactChunksMut<'a, T: CompactRepr> {
2604    packed: *mut Store<T>,
2605    start: usize,
2606    len: usize,
2607    chunk_size: usize,
2608    pos: usize,
2609    _marker: PhantomData<&'a mut Store<T>>,
2610}
2611
2612impl<'a, T: CompactRepr> Iterator for CompactChunksMut<'a, T> {
2613    type Item = CompactSliceMut<'a, T>;
2614    #[inline]
2615    fn next(&mut self) -> Option<CompactSliceMut<'a, T>> {
2616        if self.pos >= self.len || self.chunk_size == 0 {
2617            return None;
2618        }
2619        let end = (self.pos + self.chunk_size).min(self.len);
2620        let result = CompactSliceMut {
2621            packed: self.packed,
2622            start: self.start + self.pos,
2623            len: end - self.pos,
2624            _marker: PhantomData,
2625        };
2626        self.pos = end;
2627        Some(result)
2628    }
2629    #[inline]
2630    fn size_hint(&self) -> (usize, Option<usize>) {
2631        if self.chunk_size == 0 {
2632            return (0, Some(0));
2633        }
2634        // Non-overflowing ceiling division (see `CompactChunks`).
2635        let r = self.len.saturating_sub(self.pos);
2636        let c = r / self.chunk_size + usize::from(r % self.chunk_size != 0);
2637        (c, Some(c))
2638    }
2639    #[inline]
2640    fn count(self) -> usize {
2641        self.size_hint().0
2642    }
2643}
2644
2645impl<T: CompactRepr> ExactSizeIterator for CompactChunksMut<'_, T> {}
2646
2647pub struct CompactChunksExactMut<'a, T: CompactRepr> {
2648    packed: *mut Store<T>,
2649    start: usize,
2650    len: usize,
2651    chunk_size: usize,
2652    pos: usize,
2653    end: usize,
2654    _marker: PhantomData<&'a mut Store<T>>,
2655}
2656
2657impl<'a, T: CompactRepr> Iterator for CompactChunksExactMut<'a, T> {
2658    type Item = CompactSliceMut<'a, T>;
2659    #[inline]
2660    fn next(&mut self) -> Option<CompactSliceMut<'a, T>> {
2661        if self.pos >= self.end || self.chunk_size == 0 {
2662            return None;
2663        }
2664        let result = CompactSliceMut {
2665            packed: self.packed,
2666            start: self.start + self.pos,
2667            len: self.chunk_size,
2668            _marker: PhantomData,
2669        };
2670        self.pos += self.chunk_size;
2671        Some(result)
2672    }
2673    #[inline]
2674    fn size_hint(&self) -> (usize, Option<usize>) {
2675        if self.chunk_size == 0 {
2676            return (0, Some(0));
2677        }
2678        let r = self.end.saturating_sub(self.pos);
2679        let c = r / self.chunk_size;
2680        (c, Some(c))
2681    }
2682    #[inline]
2683    fn count(self) -> usize {
2684        self.size_hint().0
2685    }
2686}
2687
2688impl<T: CompactRepr> ExactSizeIterator for CompactChunksExactMut<'_, T> {}
2689
2690#[allow(dead_code)]
2691impl<'a, T: CompactRepr> CompactChunksExactMut<'a, T> {
2692    pub fn into_remainder(self) -> CompactSliceMut<'a, T> {
2693        let rem_start = self.end.min(self.len);
2694        CompactSliceMut {
2695            packed: self.packed,
2696            start: self.start + rem_start,
2697            len: self.len - rem_start,
2698            _marker: PhantomData,
2699        }
2700    }
2701}
2702
2703// ---------------------------------------------------------------------------
2704// SoAIndex / SoAIndexMut for CompactSlice / CompactSliceMut
2705// ---------------------------------------------------------------------------
2706
2707impl<'a, T: CompactRepr> crate::SoAIndex<CompactSlice<'a, T>> for usize {
2708    type RefOutput = Compact<T>;
2709    #[inline]
2710    fn get(self, slice: CompactSlice<'a, T>) -> Option<Self::RefOutput> {
2711        slice.get(self)
2712    }
2713    #[inline]
2714    unsafe fn get_unchecked(
2715        self,
2716        slice: CompactSlice<'a, T>,
2717    ) -> Self::RefOutput {
2718        slice.get_unchecked(self)
2719    }
2720    #[inline]
2721    fn index(self, slice: CompactSlice<'a, T>) -> Self::RefOutput {
2722        slice.index(self)
2723    }
2724}
2725
2726impl<'a, T: CompactRepr> crate::SoAIndexMut<CompactSliceMut<'a, T>> for usize {
2727    type MutOutput = CompactRefMut<'a, T>;
2728    #[inline]
2729    fn get_mut(self, slice: CompactSliceMut<'a, T>) -> Option<Self::MutOutput> {
2730        if self < slice.len {
2731            unsafe {
2732                Some(CompactRefMut::from_packed_ptr(
2733                    slice.packed,
2734                    slice.start + self,
2735                ))
2736            }
2737        } else {
2738            None
2739        }
2740    }
2741    #[inline]
2742    unsafe fn get_unchecked_mut(
2743        self,
2744        slice: CompactSliceMut<'a, T>,
2745    ) -> Self::MutOutput {
2746        CompactRefMut::from_packed_ptr(slice.packed, slice.start + self)
2747    }
2748    #[inline]
2749    fn index_mut(self, slice: CompactSliceMut<'a, T>) -> Self::MutOutput {
2750        assert!(self < slice.len);
2751        unsafe {
2752            CompactRefMut::from_packed_ptr(slice.packed, slice.start + self)
2753        }
2754    }
2755}
2756
2757impl<'a, T: CompactRepr> crate::SoAIndex<CompactSlice<'a, T>>
2758    for core::ops::Range<usize>
2759{
2760    type RefOutput = CompactSlice<'a, T>;
2761    #[inline]
2762    fn get(self, slice: CompactSlice<'a, T>) -> Option<Self::RefOutput> {
2763        if self.start <= self.end && self.end <= slice.len {
2764            Some(CompactSlice {
2765                packed: slice.packed,
2766                start: slice.start + self.start,
2767                len: self.end - self.start,
2768                _marker: PhantomData,
2769            })
2770        } else {
2771            None
2772        }
2773    }
2774    #[inline]
2775    unsafe fn get_unchecked(
2776        self,
2777        slice: CompactSlice<'a, T>,
2778    ) -> Self::RefOutput {
2779        CompactSlice {
2780            packed: slice.packed,
2781            start: slice.start + self.start,
2782            len: self.end - self.start,
2783            _marker: PhantomData,
2784        }
2785    }
2786    #[inline]
2787    fn index(self, slice: CompactSlice<'a, T>) -> Self::RefOutput {
2788        assert!(self.start <= self.end && self.end <= slice.len);
2789        CompactSlice {
2790            packed: slice.packed,
2791            start: slice.start + self.start,
2792            len: self.end - self.start,
2793            _marker: PhantomData,
2794        }
2795    }
2796}
2797
2798impl<'a, T: CompactRepr> crate::SoAIndexMut<CompactSliceMut<'a, T>>
2799    for core::ops::Range<usize>
2800{
2801    type MutOutput = CompactSliceMut<'a, T>;
2802    #[inline]
2803    fn get_mut(self, slice: CompactSliceMut<'a, T>) -> Option<Self::MutOutput> {
2804        if self.start <= self.end && self.end <= slice.len {
2805            Some(CompactSliceMut {
2806                packed: slice.packed,
2807                start: slice.start + self.start,
2808                len: self.end - self.start,
2809                _marker: PhantomData,
2810            })
2811        } else {
2812            None
2813        }
2814    }
2815    #[inline]
2816    unsafe fn get_unchecked_mut(
2817        self,
2818        slice: CompactSliceMut<'a, T>,
2819    ) -> Self::MutOutput {
2820        CompactSliceMut {
2821            packed: slice.packed,
2822            start: slice.start + self.start,
2823            len: self.end - self.start,
2824            _marker: PhantomData,
2825        }
2826    }
2827    #[inline]
2828    fn index_mut(self, slice: CompactSliceMut<'a, T>) -> Self::MutOutput {
2829        assert!(self.start <= self.end && self.end <= slice.len);
2830        CompactSliceMut {
2831            packed: slice.packed,
2832            start: slice.start + self.start,
2833            len: self.end - self.start,
2834            _marker: PhantomData,
2835        }
2836    }
2837}
2838
2839impl<'a, T: CompactRepr> crate::SoAIndex<CompactSlice<'a, T>>
2840    for core::ops::RangeTo<usize>
2841{
2842    type RefOutput = CompactSlice<'a, T>;
2843    #[inline]
2844    fn get(self, s: CompactSlice<'a, T>) -> Option<Self::RefOutput> {
2845        crate::SoAIndex::get(0..self.end, s)
2846    }
2847    #[inline]
2848    unsafe fn get_unchecked(self, s: CompactSlice<'a, T>) -> Self::RefOutput {
2849        crate::SoAIndex::get_unchecked(0..self.end, s)
2850    }
2851    #[inline]
2852    fn index(self, s: CompactSlice<'a, T>) -> Self::RefOutput {
2853        crate::SoAIndex::index(0..self.end, s)
2854    }
2855}
2856
2857impl<'a, T: CompactRepr> crate::SoAIndexMut<CompactSliceMut<'a, T>>
2858    for core::ops::RangeTo<usize>
2859{
2860    type MutOutput = CompactSliceMut<'a, T>;
2861    #[inline]
2862    fn get_mut(self, s: CompactSliceMut<'a, T>) -> Option<Self::MutOutput> {
2863        crate::SoAIndexMut::get_mut(0..self.end, s)
2864    }
2865    #[inline]
2866    unsafe fn get_unchecked_mut(
2867        self,
2868        s: CompactSliceMut<'a, T>,
2869    ) -> Self::MutOutput {
2870        crate::SoAIndexMut::get_unchecked_mut(0..self.end, s)
2871    }
2872    #[inline]
2873    fn index_mut(self, s: CompactSliceMut<'a, T>) -> Self::MutOutput {
2874        crate::SoAIndexMut::index_mut(0..self.end, s)
2875    }
2876}
2877
2878impl<'a, T: CompactRepr> crate::SoAIndex<CompactSlice<'a, T>>
2879    for core::ops::RangeFrom<usize>
2880{
2881    type RefOutput = CompactSlice<'a, T>;
2882    #[inline]
2883    fn get(self, s: CompactSlice<'a, T>) -> Option<Self::RefOutput> {
2884        if self.start <= s.len {
2885            Some(CompactSlice {
2886                packed: s.packed,
2887                start: s.start + self.start,
2888                len: s.len - self.start,
2889                _marker: PhantomData,
2890            })
2891        } else {
2892            None
2893        }
2894    }
2895    #[inline]
2896    unsafe fn get_unchecked(self, s: CompactSlice<'a, T>) -> Self::RefOutput {
2897        CompactSlice {
2898            packed: s.packed,
2899            start: s.start + self.start,
2900            len: s.len - self.start,
2901            _marker: PhantomData,
2902        }
2903    }
2904    #[inline]
2905    fn index(self, s: CompactSlice<'a, T>) -> Self::RefOutput {
2906        assert!(self.start <= s.len);
2907        CompactSlice {
2908            packed: s.packed,
2909            start: s.start + self.start,
2910            len: s.len - self.start,
2911            _marker: PhantomData,
2912        }
2913    }
2914}
2915
2916impl<'a, T: CompactRepr> crate::SoAIndexMut<CompactSliceMut<'a, T>>
2917    for core::ops::RangeFrom<usize>
2918{
2919    type MutOutput = CompactSliceMut<'a, T>;
2920    #[inline]
2921    fn get_mut(self, s: CompactSliceMut<'a, T>) -> Option<Self::MutOutput> {
2922        if self.start <= s.len {
2923            Some(CompactSliceMut {
2924                packed: s.packed,
2925                start: s.start + self.start,
2926                len: s.len - self.start,
2927                _marker: PhantomData,
2928            })
2929        } else {
2930            None
2931        }
2932    }
2933    #[inline]
2934    unsafe fn get_unchecked_mut(
2935        self,
2936        s: CompactSliceMut<'a, T>,
2937    ) -> Self::MutOutput {
2938        CompactSliceMut {
2939            packed: s.packed,
2940            start: s.start + self.start,
2941            len: s.len - self.start,
2942            _marker: PhantomData,
2943        }
2944    }
2945    #[inline]
2946    fn index_mut(self, s: CompactSliceMut<'a, T>) -> Self::MutOutput {
2947        assert!(self.start <= s.len);
2948        CompactSliceMut {
2949            packed: s.packed,
2950            start: s.start + self.start,
2951            len: s.len - self.start,
2952            _marker: PhantomData,
2953        }
2954    }
2955}
2956
2957impl<'a, T: CompactRepr> crate::SoAIndex<CompactSlice<'a, T>>
2958    for core::ops::RangeFull
2959{
2960    type RefOutput = CompactSlice<'a, T>;
2961    #[inline]
2962    fn get(self, s: CompactSlice<'a, T>) -> Option<Self::RefOutput> {
2963        Some(s)
2964    }
2965    #[inline]
2966    unsafe fn get_unchecked(self, s: CompactSlice<'a, T>) -> Self::RefOutput {
2967        s
2968    }
2969    #[inline]
2970    fn index(self, s: CompactSlice<'a, T>) -> Self::RefOutput {
2971        s
2972    }
2973}
2974
2975impl<'a, T: CompactRepr> crate::SoAIndexMut<CompactSliceMut<'a, T>>
2976    for core::ops::RangeFull
2977{
2978    type MutOutput = CompactSliceMut<'a, T>;
2979    #[inline]
2980    fn get_mut(self, s: CompactSliceMut<'a, T>) -> Option<Self::MutOutput> {
2981        Some(s)
2982    }
2983    #[inline]
2984    unsafe fn get_unchecked_mut(
2985        self,
2986        s: CompactSliceMut<'a, T>,
2987    ) -> Self::MutOutput {
2988        s
2989    }
2990    #[inline]
2991    fn index_mut(self, s: CompactSliceMut<'a, T>) -> Self::MutOutput {
2992        s
2993    }
2994}
2995
2996impl<'a, T: CompactRepr> crate::SoAIndex<CompactSlice<'a, T>>
2997    for core::ops::RangeInclusive<usize>
2998{
2999    type RefOutput = CompactSlice<'a, T>;
3000    #[inline]
3001    fn get(self, s: CompactSlice<'a, T>) -> Option<Self::RefOutput> {
3002        if *self.end() == usize::MAX {
3003            None
3004        } else {
3005            crate::SoAIndex::get(*self.start()..self.end().saturating_add(1), s)
3006        }
3007    }
3008    #[inline]
3009    unsafe fn get_unchecked(self, s: CompactSlice<'a, T>) -> Self::RefOutput {
3010        crate::SoAIndex::get_unchecked(
3011            *self.start()..self.end().saturating_add(1),
3012            s,
3013        )
3014    }
3015    #[inline]
3016    fn index(self, s: CompactSlice<'a, T>) -> Self::RefOutput {
3017        crate::SoAIndex::index(*self.start()..self.end().saturating_add(1), s)
3018    }
3019}
3020
3021impl<'a, T: CompactRepr> crate::SoAIndexMut<CompactSliceMut<'a, T>>
3022    for core::ops::RangeInclusive<usize>
3023{
3024    type MutOutput = CompactSliceMut<'a, T>;
3025    #[inline]
3026    fn get_mut(self, s: CompactSliceMut<'a, T>) -> Option<Self::MutOutput> {
3027        if *self.end() == usize::MAX {
3028            None
3029        } else {
3030            crate::SoAIndexMut::get_mut(
3031                *self.start()..self.end().saturating_add(1),
3032                s,
3033            )
3034        }
3035    }
3036    #[inline]
3037    unsafe fn get_unchecked_mut(
3038        self,
3039        s: CompactSliceMut<'a, T>,
3040    ) -> Self::MutOutput {
3041        crate::SoAIndexMut::get_unchecked_mut(
3042            *self.start()..self.end().saturating_add(1),
3043            s,
3044        )
3045    }
3046    #[inline]
3047    fn index_mut(self, s: CompactSliceMut<'a, T>) -> Self::MutOutput {
3048        crate::SoAIndexMut::index_mut(
3049            *self.start()..self.end().saturating_add(1),
3050            s,
3051        )
3052    }
3053}
3054
3055impl<'a, T: CompactRepr> crate::SoAIndex<CompactSlice<'a, T>>
3056    for core::ops::RangeToInclusive<usize>
3057{
3058    type RefOutput = CompactSlice<'a, T>;
3059    #[inline]
3060    fn get(self, s: CompactSlice<'a, T>) -> Option<Self::RefOutput> {
3061        if self.end == usize::MAX {
3062            None
3063        } else {
3064            crate::SoAIndex::get(0..self.end.saturating_add(1), s)
3065        }
3066    }
3067    #[inline]
3068    unsafe fn get_unchecked(self, s: CompactSlice<'a, T>) -> Self::RefOutput {
3069        crate::SoAIndex::get_unchecked(0..self.end.saturating_add(1), s)
3070    }
3071    #[inline]
3072    fn index(self, s: CompactSlice<'a, T>) -> Self::RefOutput {
3073        crate::SoAIndex::index(0..self.end.saturating_add(1), s)
3074    }
3075}
3076
3077impl<'a, T: CompactRepr> crate::SoAIndexMut<CompactSliceMut<'a, T>>
3078    for core::ops::RangeToInclusive<usize>
3079{
3080    type MutOutput = CompactSliceMut<'a, T>;
3081    #[inline]
3082    fn get_mut(self, s: CompactSliceMut<'a, T>) -> Option<Self::MutOutput> {
3083        if self.end == usize::MAX {
3084            None
3085        } else {
3086            crate::SoAIndexMut::get_mut(0..self.end.saturating_add(1), s)
3087        }
3088    }
3089    #[inline]
3090    unsafe fn get_unchecked_mut(
3091        self,
3092        s: CompactSliceMut<'a, T>,
3093    ) -> Self::MutOutput {
3094        crate::SoAIndexMut::get_unchecked_mut(0..self.end.saturating_add(1), s)
3095    }
3096    #[inline]
3097    fn index_mut(self, s: CompactSliceMut<'a, T>) -> Self::MutOutput {
3098        crate::SoAIndexMut::index_mut(0..self.end.saturating_add(1), s)
3099    }
3100}