soa_rs/
soa.rs

1use crate::{
2    iter_raw::IterRaw, AsMutSlice, AsSlice, IntoIter, Iter, IterMut, Slice, SliceMut, SliceRef,
3    SoaRaw, Soars,
4};
5use std::{
6    borrow::{Borrow, BorrowMut},
7    cmp::Ordering,
8    fmt::{self, Debug, Formatter},
9    hash::{Hash, Hasher},
10    marker::PhantomData,
11    mem::{needs_drop, size_of, ManuallyDrop},
12    ops::{Deref, DerefMut},
13    ptr::NonNull,
14};
15
16/// A growable array type that stores the values for each field of `T`
17/// contiguously.
18///
19/// The design for SoA aligns closely with [`Vec`]:
20/// - Overallocates capacity to provide O(1) amortized insertion
21/// - Does not allocate until elements are added
22/// - Never deallocates memory unless explicitly requested
23/// - Uses `usize::MAX` as the capacity for zero-sized types
24///
25/// See the top-level [`soa_rs`] docs for usage examples.
26///
27/// [`soa_rs`]: crate
28pub struct Soa<T>
29where
30    T: Soars,
31{
32    pub(crate) cap: usize,
33    pub(crate) slice: Slice<T, ()>,
34    pub(crate) len: usize,
35}
36
37impl<T> Soa<T>
38where
39    T: Soars,
40{
41    /// The capacity of the initial allocation. This is an optimization to avoid
42    /// excessive reallocation for small array sizes.
43    const SMALL_CAPACITY: usize = 4;
44
45    /// Constructs a new, empty `Soa<T>`.
46    ///
47    /// The container will not allocate until elements are pushed onto it.
48    ///
49    /// # Examples
50    /// ```
51    /// # use soa_rs::{Soa, Soars};
52    /// # #[derive(Soars, Copy, Clone)]
53    /// # #[soa_derive(Debug, PartialEq)]
54    /// # struct Foo;
55    /// let mut soa = Soa::<Foo>::new();
56    /// ```
57    pub fn new() -> Self {
58        Self {
59            cap: if size_of::<T>() == 0 { usize::MAX } else { 0 },
60            slice: Slice::empty(),
61            len: 0,
62        }
63    }
64
65    /// Construct a new, empty `Soa<T>` with at least the specified capacity.
66    ///
67    /// The container will be able to hold `capacity` elements without
68    /// reallocating. If the `capacity` is 0, the container will not allocate.
69    /// Note that although the returned vector has the minimum capacity
70    /// specified, the vector will have a zero length. The capacity will be as
71    /// specified unless `T` is zero-sized, in which case the capacity will be
72    /// `usize::MAX`.
73    ///
74    /// # Examples
75    /// ```
76    /// # use soa_rs::{Soa, Soars};
77    /// #[derive(Soars)]
78    /// # #[soa_derive(Debug, PartialEq)]
79    /// struct Foo(u8, u8);
80    ///
81    /// let mut soa = Soa::<Foo>::with_capacity(10);
82    /// assert_eq!(soa.len(), 0);
83    /// assert_eq!(soa.capacity(), 10);
84    ///
85    /// // These pushes do not reallocate...
86    /// for i in 0..10 {
87    ///     soa.push(Foo(i, i));
88    /// }
89    /// assert_eq!(soa.len(), 10);
90    /// assert_eq!(soa.capacity(), 10);
91    ///
92    /// // ...but this one does
93    /// soa.push(Foo(11, 11));
94    /// assert_eq!(soa.len(), 11);
95    /// assert_eq!(soa.capacity(), 20);
96    ///
97    /// #[derive(Soars, Copy, Clone)]
98    /// # #[soa_derive(Debug, PartialEq)]
99    /// struct Bar;
100    ///
101    /// // A SOA of a zero-sized type always over-allocates
102    /// let soa = Soa::<Bar>::with_capacity(10);
103    /// assert_eq!(soa.capacity(), usize::MAX);
104    /// ```
105    pub fn with_capacity(capacity: usize) -> Self {
106        match capacity {
107            0 => Self::new(),
108            capacity => {
109                if size_of::<T>() == 0 {
110                    Self {
111                        cap: usize::MAX,
112                        slice: Slice::empty(),
113                        len: 0,
114                    }
115                } else {
116                    Self {
117                        cap: capacity,
118                        // SAFETY:
119                        // - T is nonzero sized
120                        // - capacity is nonzero
121                        slice: Slice::with_raw(unsafe { T::Raw::alloc(capacity) }),
122                        len: 0,
123                    }
124                }
125            }
126        }
127    }
128
129    /// Constructs a new `Soa<T>` with the given first element.
130    ///
131    /// This is mainly useful to get around type inference limitations in some
132    /// situations, namely macros. Type inference can struggle sometimes due to
133    /// dereferencing to an associated type of `T`, which causes Rust to get
134    /// confused about whether, for example, `push`ing and element should coerce
135    /// `self` to the argument's type.
136    ///
137    /// # Examples
138    ///
139    /// ```
140    /// # use soa_rs::{Soa, Soars, soa};
141    /// # #[derive(Soars, Debug, PartialEq)]
142    /// # #[soa_derive(Debug, PartialEq)]
143    /// # struct Foo(usize);
144    /// let soa = Soa::with(Foo(10));
145    /// assert_eq!(soa, soa![Foo(10)]);
146    /// ```
147    pub fn with(element: T) -> Self {
148        let mut out = Self::new();
149        out.push(element);
150        out
151    }
152
153    /// Returns the total number of elements the container can hold without
154    /// reallocating.
155    ///
156    /// # Examples
157    ///
158    /// ```
159    /// # use soa_rs::{Soa, Soars};
160    /// # #[derive(Soars)]
161    /// # #[soa_derive(Debug, PartialEq)]
162    /// # struct Foo(usize);
163    /// let mut soa = Soa::<Foo>::new();
164    /// for i in 0..42 {
165    ///     assert!(soa.capacity() >= i);
166    ///     soa.push(Foo(i));
167    /// }
168    /// ```
169    pub fn capacity(&self) -> usize {
170        self.cap
171    }
172
173    /// Decomposes a `Soa<T>` into its raw components.
174    ///
175    /// Returns the raw pointer to the underlying data, the length of the vector (in
176    /// elements), and the allocated capacity of the data (in elements). These
177    /// are the same arguments in the same order as the arguments to
178    /// [`Soa::from_raw_parts`].
179    ///
180    /// After calling this function, the caller is responsible for the memory
181    /// previously managed by the `Soa`. The only way to do this is to convert the
182    /// raw pointer, length, and capacity back into a Vec with the
183    /// [`Soa::from_raw_parts`] function, allowing the destructor to perform the cleanup.
184    ///
185    /// # Examples
186    ///
187    /// ```
188    /// # use soa_rs::{Soa, Soars, soa};
189    /// # #[derive(Soars, Debug, PartialEq)]
190    /// # #[soa_derive(Debug, PartialEq)]
191    /// # struct Foo(usize);
192    /// let soa = soa![Foo(1), Foo(2)];
193    /// let (ptr, len, cap) = soa.into_raw_parts();
194    /// let rebuilt = unsafe { Soa::<Foo>::from_raw_parts(ptr, len, cap) };
195    /// assert_eq!(rebuilt, soa![Foo(1), Foo(2)]);
196    /// ```
197    pub fn into_raw_parts(self) -> (NonNull<u8>, usize, usize) {
198        let me = ManuallyDrop::new(self);
199        (me.raw().into_parts(), me.len, me.cap)
200    }
201
202    /// Creates a `Soa<T>` from a pointer, a length, and a capacity.
203    ///
204    /// # Safety
205    ///
206    /// This is highly unsafe due to the number of invariants that aren't
207    /// checked. Given that many of these invariants are private implementation
208    /// details of [`SoaRaw`], it is better not to uphold them manually. Rather,
209    /// it only valid to call this method with the output of a previous call to
210    /// [`Soa::into_raw_parts`].
211    pub unsafe fn from_raw_parts(ptr: NonNull<u8>, length: usize, capacity: usize) -> Self {
212        let raw = unsafe { T::Raw::from_parts(ptr, capacity) };
213        Self {
214            cap: capacity,
215            slice: Slice::with_raw(raw),
216            len: length,
217        }
218    }
219
220    /// Appends an element to the back of a collection.
221    ///
222    /// # Examples
223    ///
224    /// ```
225    /// # use soa_rs::{Soa, Soars, soa};
226    /// # #[derive(Soars, Debug, PartialEq)]
227    /// # #[soa_derive(Debug, PartialEq)]
228    /// # struct Foo(usize);
229    /// let mut soa = soa![Foo(1), Foo(2)];
230    /// soa.push(Foo(3));
231    /// assert_eq!(soa, soa![Foo(1), Foo(2), Foo(3)]);
232    /// ```
233    pub fn push(&mut self, element: T) {
234        self.maybe_grow();
235        // SAFETY: After maybe_grow, the allocated capacity is greater than len
236        unsafe {
237            self.raw().offset(self.len).set(element);
238        }
239        self.len += 1;
240    }
241
242    /// Removes the last element from a vector and returns it, or [`None`] if it
243    /// is empty.
244    ///
245    /// # Examples
246    ///
247    /// ```
248    /// # use soa_rs::{Soa, Soars, soa};
249    /// # #[derive(Soars, Debug, PartialEq)]
250    /// # #[soa_derive(Debug, PartialEq)]
251    /// # struct Foo(usize);
252    /// let mut soa = soa![Foo(1), Foo(2), Foo(3)];
253    /// assert_eq!(soa.pop(), Some(Foo(3)));
254    /// assert_eq!(soa, soa![Foo(1), Foo(2)]);
255    /// ```
256    pub fn pop(&mut self) -> Option<T> {
257        if self.len == 0 {
258            None
259        } else {
260            self.len -= 1;
261            // SAFETY: len points to at least one initialized item
262            Some(unsafe { self.raw().offset(self.len).get() })
263        }
264    }
265
266    /// Inserts an element at position `index`, shifting all elements after it
267    /// to the right.
268    ///
269    /// # Panics
270    ///
271    /// Panics if `index > len`
272    ///
273    /// # Examples
274    ///
275    /// ```
276    /// # use soa_rs::{Soa, Soars, soa};
277    /// # #[derive(Soars, Debug, PartialEq)]
278    /// # #[soa_derive(Debug, PartialEq)]
279    /// # struct Foo(usize);
280    /// let mut soa = soa![Foo(1), Foo(2), Foo(3)];
281    /// soa.insert(1, Foo(4));
282    /// assert_eq!(soa, soa![Foo(1), Foo(4), Foo(2), Foo(3)]);
283    /// soa.insert(4, Foo(5));
284    /// assert_eq!(soa, soa![Foo(1), Foo(4), Foo(2), Foo(3), Foo(5)]);
285    /// ```
286    pub fn insert(&mut self, index: usize, element: T) {
287        assert!(index <= self.len, "index out of bounds");
288        self.maybe_grow();
289        // SAFETY: After the bounds check and maybe_grow, index is an
290        // initialized item and index+1 is allocated
291        unsafe {
292            let ith = self.raw().offset(index);
293            ith.copy_to(ith.offset(1), self.len - index);
294            ith.set(element);
295        }
296        self.len += 1;
297    }
298
299    /// Removes and returns the element at position index within the vector,
300    /// shifting all elements after it to the left.
301    ///
302    /// # Examples
303    ///
304    /// ```
305    /// # use soa_rs::{Soa, Soars, soa};
306    /// # #[derive(Soars, Debug, PartialEq)]
307    /// # #[soa_derive(Debug, PartialEq)]
308    /// # struct Foo(usize);
309    /// let mut soa = soa![Foo(1), Foo(2), Foo(3)];
310    /// assert_eq!(soa.remove(1), Foo(2));
311    /// assert_eq!(soa, soa![Foo(1), Foo(3)])
312    /// ```
313    pub fn remove(&mut self, index: usize) -> T {
314        assert!(index < self.len, "index out of bounds");
315        self.len -= 1;
316        // SAFETY: After the bounds check, we know ith item is initialized
317        let ith = unsafe { self.raw().offset(index) };
318        let out = unsafe { ith.get() };
319        // SAFETY: There are len-index initialized elements to shift back
320        unsafe {
321            ith.offset(1).copy_to(ith, self.len - index);
322        }
323        out
324    }
325
326    /// Reserves capacity for at least additional more elements to be inserted
327    /// in the given `Soa<T>`. The collection may reserve more space to
328    /// speculatively avoid frequent reallocations. After calling reserve,
329    /// capacity will be greater than or equal to `self.len() + additional`.
330    /// Does nothing if capacity is already sufficient.
331    ///
332    /// # Examples
333    ///
334    /// ```
335    /// # use soa_rs::{Soa, Soars, soa};
336    /// # #[derive(Soars, Debug, PartialEq)]
337    /// # #[soa_derive(Debug, PartialEq)]
338    /// # struct Foo(usize);
339    /// let mut soa = soa![Foo(1)];
340    /// soa.reserve(10);
341    /// assert!(soa.capacity() >= 11);
342    /// ```
343    pub fn reserve(&mut self, additional: usize) {
344        let new_len = self.len + additional;
345        if new_len > self.cap {
346            let new_cap = new_len
347                // Ensure exponential growth
348                .max(self.cap * 2)
349                .max(Self::SMALL_CAPACITY);
350            self.grow(new_cap);
351        }
352    }
353
354    /// Reserves the minimum capacity for at least additional more elements to
355    /// be inserted in the given `Soa<T>`. Unlike [`Soa::reserve`], this will
356    /// not deliberately over-allocate to speculatively avoid frequent
357    /// allocations. After calling `reserve_exact`, capacity will be equal to
358    /// self.len() + additional, or else `usize::MAX` if `T` is zero-sized. Does
359    /// nothing if the capacity is already sufficient.
360    ///
361    /// # Examples
362    ///
363    /// ```
364    /// # use soa_rs::{Soa, Soars, soa};
365    /// # #[derive(Soars, Debug, PartialEq)]
366    /// # #[soa_derive(Debug, PartialEq)]
367    /// # struct Foo(usize);
368    /// let mut soa = soa![Foo(1)];
369    /// soa.reserve(10);
370    /// assert!(soa.capacity() == 11);
371    /// ```
372    pub fn reserve_exact(&mut self, additional: usize) {
373        let new_len = additional + self.len;
374        if new_len > self.cap {
375            self.grow(new_len);
376        }
377    }
378
379    /// Shrinks the capacity of the container as much as possible.
380    ///
381    /// # Examples
382    ///
383    /// ```
384    /// # use soa_rs::{Soa, Soars, soa};
385    /// # #[derive(Soars, Debug, PartialEq)]
386    /// # #[soa_derive(Debug, PartialEq)]
387    /// # struct Foo(usize);
388    /// let mut soa = Soa::<Foo>::with_capacity(10);
389    /// soa.extend([Foo(1), Foo(2), Foo(3)]);
390    /// assert_eq!(soa.capacity(), 10);
391    /// soa.shrink_to_fit();
392    /// assert_eq!(soa.capacity(), 3);
393    /// ```
394    pub fn shrink_to_fit(&mut self) {
395        self.shrink(self.len);
396    }
397
398    /// Shrinks the capacity of the vector with a lower bound.
399    ///
400    /// The capacity will remain at least as large as both the length and the
401    /// supplied value. If the current capacity is less than the lower limit,
402    /// this is a no-op.
403    ///
404    /// # Examples
405    ///
406    /// ```
407    /// # use soa_rs::{Soa, Soars, soa};
408    /// # #[derive(Soars, Debug, PartialEq)]
409    /// # #[soa_derive(Debug, PartialEq)]
410    /// # struct Foo(usize);
411    /// let mut soa = Soa::<Foo>::with_capacity(10);
412    /// soa.extend([Foo(1), Foo(2), Foo(3)]);
413    /// assert_eq!(soa.capacity(), 10);
414    /// soa.shrink_to(4);
415    /// assert_eq!(soa.capacity(), 4);
416    /// soa.shrink_to(0);
417    /// assert_eq!(soa.capacity(), 3);
418    pub fn shrink_to(&mut self, min_capacity: usize) {
419        let new_cap = self.len.max(min_capacity);
420        if new_cap < self.cap {
421            self.shrink(new_cap);
422        }
423    }
424
425    /// Shortens the vector, keeping the first len elements and dropping the rest.
426    ///
427    /// If len is greater or equal to the vector’s current length, this has no
428    /// effect. Note that this method has no effect on the allocated capacity of
429    /// the vector.
430    ///
431    /// # Examples
432    ///
433    /// Truncating a five-element SOA to two elements:
434    /// ```
435    /// # use soa_rs::{Soa, Soars, soa};
436    /// # #[derive(Soars, Debug, PartialEq)]
437    /// # #[soa_derive(Debug, PartialEq)]
438    /// # struct Foo(usize);
439    /// let mut soa = soa![Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)];
440    /// soa.truncate(2);
441    /// assert_eq!(soa, soa![Foo(1), Foo(2)]);
442    /// ```
443    ///
444    /// No truncation occurs when `len` is greater than the SOA's current
445    /// length:
446    /// ```
447    /// # use soa_rs::{Soa, Soars, soa};
448    /// # #[derive(Soars, Debug, PartialEq)]
449    /// # #[soa_derive(Debug, PartialEq)]
450    /// # struct Foo(usize);
451    /// let mut soa = soa![Foo(1), Foo(2), Foo(3)];
452    /// soa.truncate(8);
453    /// assert_eq!(soa, soa![Foo(1), Foo(2), Foo(3)]);
454    /// ```
455    ///
456    /// Truncating with `len == 0` is equivalent to [`Soa::clear`].
457    /// ```
458    /// # use soa_rs::{Soa, Soars, soa};
459    /// # #[derive(Soars, Debug, PartialEq)]
460    /// # #[soa_derive(Debug, PartialEq)]
461    /// # struct Foo(usize);
462    /// let mut soa = soa![Foo(1), Foo(2), Foo(3)];
463    /// soa.truncate(0);
464    /// assert_eq!(soa, soa![]);
465    /// ```
466    pub fn truncate(&mut self, len: usize) {
467        while len < self.len {
468            self.pop();
469        }
470    }
471
472    /// Removes an element from the vector and returns it.
473    ///
474    /// The removed element is replaced by the last element of the vector. This
475    /// does not preserve ordering, but is O(1). If you need to preserve the
476    /// element order, use remove instead.
477    ///
478    /// # Panics
479    ///
480    /// Panics if index is out of bounds.
481    ///
482    /// # Examples
483    ///
484    /// ```
485    /// # use soa_rs::{Soa, Soars, soa};
486    /// # #[derive(Soars, Debug, PartialEq)]
487    /// # #[soa_derive(Debug, PartialEq)]
488    /// # struct Foo(usize);
489    /// let mut soa = soa![Foo(0), Foo(1), Foo(2), Foo(3)];
490    ///
491    /// assert_eq!(soa.swap_remove(1), Foo(1));
492    /// assert_eq!(soa, soa![Foo(0), Foo(3), Foo(2)]);
493    ///
494    /// assert_eq!(soa.swap_remove(0), Foo(0));
495    /// assert_eq!(soa, soa![Foo(2), Foo(3)])
496    /// ```
497    pub fn swap_remove(&mut self, index: usize) -> T {
498        if index >= self.len {
499            panic!("index out of bounds")
500        }
501        self.len -= 1;
502        // SAFETY: index and len-1 are initialized elements
503        let to_remove = unsafe { self.raw().offset(index) };
504        let last = unsafe { self.raw().offset(self.len) };
505        let out = unsafe { to_remove.get() };
506        unsafe {
507            last.copy_to(to_remove, 1);
508        }
509        out
510    }
511
512    /// Moves all the elements of other into self, leaving other empty.
513    ///
514    /// # Examples
515    ///
516    /// ```
517    /// # use soa_rs::{Soa, Soars, soa};
518    /// # #[derive(Soars, Debug, PartialEq)]
519    /// # #[soa_derive(Debug, PartialEq)]
520    /// # struct Foo(usize);
521    /// let mut soa1  = soa![Foo(1), Foo(2), Foo(3)];
522    /// let mut soa2 = soa![Foo(4), Foo(5), Foo(6)];
523    /// soa1.append(&mut soa2);
524    /// assert_eq!(soa1, soa![Foo(1), Foo(2), Foo(3), Foo(4), Foo(5), Foo(6)]);
525    /// assert_eq!(soa2, soa![]);
526    /// ```
527    pub fn append(&mut self, other: &mut Self) {
528        self.reserve(other.len);
529        for i in 0..other.len {
530            // SAFETY: i is in bounds
531            let element = unsafe { other.raw().offset(i).get() };
532            self.push(element);
533        }
534        other.clear();
535    }
536
537    /// Clears the vector, removing all values.
538    ///
539    /// Note that this method has no effect on the allocated capacity of the
540    /// vector.
541    ///
542    /// # Examples
543    ///
544    /// ```
545    /// # use soa_rs::{Soa, Soars, soa};
546    /// # #[derive(Soars, Debug, PartialEq)]
547    /// # #[soa_derive(Debug, PartialEq)]
548    /// # struct Foo(usize);
549    /// let mut soa = soa![Foo(1), Foo(2)];
550    /// soa.clear();
551    /// assert!(soa.is_empty());
552    /// ```
553    pub fn clear(&mut self) {
554        while self.pop().is_some() {}
555    }
556
557    /// Grows the allocated capacity if `len == cap`.
558    fn maybe_grow(&mut self) {
559        if self.len < self.cap {
560            return;
561        }
562        let new_cap = match self.cap {
563            0 => Self::SMALL_CAPACITY,
564            old_cap => old_cap * 2,
565        };
566        self.grow(new_cap);
567    }
568
569    // Shrinks the allocated capacity.
570    fn shrink(&mut self, new_cap: usize) {
571        debug_assert!(new_cap <= self.cap);
572        if self.cap == 0 || new_cap == self.cap || size_of::<T>() == 0 {
573            return;
574        }
575
576        if new_cap == 0 {
577            debug_assert!(self.cap > 0);
578            // SAFETY: We asserted the preconditions
579            unsafe {
580                self.raw().dealloc(self.cap);
581            }
582            self.raw = T::Raw::dangling();
583        } else {
584            debug_assert!(new_cap < self.cap);
585            debug_assert!(self.len <= new_cap);
586            // SAFETY: We asserted the preconditions
587            unsafe {
588                self.raw = self.raw().realloc_shrink(self.cap, new_cap, self.len);
589            }
590        }
591
592        self.cap = new_cap;
593    }
594
595    /// Grows the allocated capacity.
596    fn grow(&mut self, new_cap: usize) {
597        debug_assert!(size_of::<T>() > 0);
598        debug_assert!(new_cap > self.cap);
599
600        if self.cap == 0 {
601            debug_assert!(new_cap > 0);
602            // SAFETY: We asserted the preconditions
603            self.raw = unsafe { T::Raw::alloc(new_cap) };
604        } else {
605            debug_assert!(self.len <= self.cap);
606            // SAFETY: We asserted the preconditions
607            unsafe {
608                self.raw = self.raw().realloc_grow(self.cap, new_cap, self.len);
609            }
610        }
611
612        self.cap = new_cap;
613    }
614}
615
616impl<T> Drop for Soa<T>
617where
618    T: Soars,
619{
620    fn drop(&mut self) {
621        if needs_drop::<T>() {
622            while self.pop().is_some() {}
623        }
624
625        if size_of::<T>() > 0 && self.cap > 0 {
626            // SAFETY: We asserted the preconditions
627            unsafe {
628                self.raw().dealloc(self.cap);
629            }
630        }
631    }
632}
633
634impl<T> IntoIterator for Soa<T>
635where
636    T: Soars,
637{
638    type Item = T;
639
640    type IntoIter = IntoIter<T>;
641
642    fn into_iter(self) -> Self::IntoIter {
643        let soa = ManuallyDrop::new(self);
644        IntoIter {
645            iter_raw: IterRaw {
646                slice: soa.slice,
647                len: soa.len,
648                adapter: PhantomData,
649            },
650            ptr: soa.raw().into_parts(),
651            cap: soa.cap,
652        }
653    }
654}
655
656impl<'a, T> IntoIterator for &'a Soa<T>
657where
658    T: Soars,
659{
660    type Item = T::Ref<'a>;
661
662    type IntoIter = Iter<'a, T>;
663
664    fn into_iter(self) -> Self::IntoIter {
665        self.deref().into_iter()
666    }
667}
668
669impl<'a, T> IntoIterator for &'a mut Soa<T>
670where
671    T: Soars,
672{
673    type Item = T::RefMut<'a>;
674
675    type IntoIter = IterMut<'a, T>;
676
677    fn into_iter(self) -> Self::IntoIter {
678        self.deref_mut().into_iter()
679    }
680}
681
682// NOTE: Copy is the required bound because calling Clone::clone on a
683// stack-allocated element is unsound in the presence of interior mutability
684// unless the fields are written back, which we also can't do because of &self.
685impl<T> Clone for Soa<T>
686where
687    T: Soars + Copy,
688{
689    fn clone(&self) -> Self {
690        let mut out = Self::with_capacity(self.len);
691        for i in 0..self.len {
692            // SAFETY: i is in-bounds
693            let el = unsafe { self.raw.offset(i).get() };
694            out.push(el);
695        }
696        out
697    }
698
699    fn clone_from(&mut self, source: &Self) {
700        self.clear();
701        self.reserve_exact(source.len);
702        for i in 0..source.len {
703            // SAFETY: i is in-bounds
704            let el = unsafe { source.raw.offset(i).get() };
705            self.push(el);
706        }
707    }
708}
709
710impl<T> Extend<T> for Soa<T>
711where
712    T: Soars,
713{
714    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
715        for item in iter {
716            self.push(item);
717        }
718    }
719}
720
721impl<T> FromIterator<T> for Soa<T>
722where
723    T: Soars,
724{
725    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
726        let iter = iter.into_iter();
727        let (hint_min, hint_max) = iter.size_hint();
728        let cap = hint_max.unwrap_or(hint_min);
729        let mut out = Self::with_capacity(cap);
730        for item in iter {
731            out.push(item);
732        }
733        out
734    }
735}
736
737impl<T, const N: usize> From<[T; N]> for Soa<T>
738where
739    T: Soars,
740{
741    /// Allocate a `Soa<T>` and move `value`'s items into it.
742    fn from(value: [T; N]) -> Self {
743        value.into_iter().collect()
744    }
745}
746
747impl<T, const N: usize> From<&[T; N]> for Soa<T>
748where
749    T: Soars + Clone,
750{
751    /// Allocate a `Soa<T>` and fill it by cloning `value`'s items.
752    fn from(value: &[T; N]) -> Self {
753        value.iter().cloned().collect()
754    }
755}
756
757impl<T, const N: usize> From<&mut [T; N]> for Soa<T>
758where
759    T: Soars + Clone,
760{
761    /// Allocate a `Soa<T>` and fill it by cloning `value`'s items.
762    fn from(value: &mut [T; N]) -> Self {
763        value.iter().cloned().collect()
764    }
765}
766
767impl<T> From<&[T]> for Soa<T>
768where
769    T: Soars + Clone,
770{
771    /// Allocate a `Soa<T>` and fill it by cloning `value`'s items.
772    fn from(value: &[T]) -> Self {
773        value.iter().cloned().collect()
774    }
775}
776
777impl<T> From<&mut [T]> for Soa<T>
778where
779    T: Soars + Clone,
780{
781    /// Allocate a `Soa<T>` and fill it by cloning `value`'s items.
782    fn from(value: &mut [T]) -> Self {
783        value.iter().cloned().collect()
784    }
785}
786
787impl<T> Debug for Soa<T>
788where
789    T: Soars,
790    for<'a> T::Ref<'a>: Debug,
791{
792    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
793        self.as_slice().fmt(f)
794    }
795}
796
797impl<T> PartialOrd for Soa<T>
798where
799    T: Soars,
800    for<'a> T::Ref<'a>: PartialOrd,
801{
802    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
803        self.as_slice().partial_cmp(&other.as_slice())
804    }
805}
806
807impl<T> Ord for Soa<T>
808where
809    T: Soars,
810    for<'a> T::Ref<'a>: Ord,
811{
812    fn cmp(&self, other: &Self) -> Ordering {
813        self.as_slice().cmp(&other.as_slice())
814    }
815}
816
817impl<T> Hash for Soa<T>
818where
819    T: Soars,
820    for<'a> T::Ref<'a>: Hash,
821{
822    fn hash<H: Hasher>(&self, state: &mut H) {
823        self.as_slice().hash(state)
824    }
825}
826
827impl<T> Default for Soa<T>
828where
829    T: Soars,
830{
831    fn default() -> Self {
832        Self::new()
833    }
834}
835
836impl<T> AsRef<Slice<T>> for Soa<T>
837where
838    T: Soars,
839{
840    fn as_ref(&self) -> &Slice<T> {
841        // SAFETY:
842        // - len is valid for the slice
843        // - The lifetime is bound to self
844        unsafe { self.slice.as_unsized(self.len) }
845    }
846}
847
848impl<T> AsMut<Slice<T>> for Soa<T>
849where
850    T: Soars,
851{
852    fn as_mut(&mut self) -> &mut Slice<T> {
853        // SAFETY:
854        // - len is valid for the slice
855        // - The lifetime is bound to self
856        unsafe { self.slice.as_unsized_mut(self.len) }
857    }
858}
859
860impl<T> AsRef<Self> for Soa<T>
861where
862    T: Soars,
863{
864    fn as_ref(&self) -> &Self {
865        self
866    }
867}
868
869impl<T> AsMut<Self> for Soa<T>
870where
871    T: Soars,
872{
873    fn as_mut(&mut self) -> &mut Self {
874        self
875    }
876}
877
878impl<T> Deref for Soa<T>
879where
880    T: Soars,
881{
882    type Target = Slice<T>;
883
884    fn deref(&self) -> &Self::Target {
885        self.as_ref()
886    }
887}
888
889impl<T> DerefMut for Soa<T>
890where
891    T: Soars,
892{
893    fn deref_mut(&mut self) -> &mut Self::Target {
894        self.as_mut()
895    }
896}
897
898impl<T> Borrow<Slice<T>> for Soa<T>
899where
900    T: Soars,
901{
902    fn borrow(&self) -> &Slice<T> {
903        self.as_ref()
904    }
905}
906
907impl<T> BorrowMut<Slice<T>> for Soa<T>
908where
909    T: Soars,
910{
911    fn borrow_mut(&mut self) -> &mut Slice<T> {
912        self.as_mut()
913    }
914}
915
916impl<T, R> PartialEq<R> for Soa<T>
917where
918    T: Soars,
919    R: AsSlice<Item = T> + ?Sized,
920    for<'a> T::Ref<'a>: PartialEq,
921{
922    fn eq(&self, other: &R) -> bool {
923        self.as_slice() == other.as_slice()
924    }
925}
926
927impl<T> Eq for Soa<T>
928where
929    T: Soars,
930    for<'a> T::Ref<'a>: Eq,
931{
932}
933
934impl<T> AsSlice for Soa<T>
935where
936    T: Soars,
937{
938    type Item = T;
939
940    fn as_slice(&self) -> SliceRef<'_, Self::Item> {
941        // SAFETY:
942        // - len is valid for this slice
943        // - The returned lifetime is bound to self
944        unsafe { SliceRef::from_slice(self.slice, self.len) }
945    }
946}
947
948impl<T> AsMutSlice for Soa<T>
949where
950    T: Soars,
951{
952    fn as_mut_slice(&mut self) -> crate::SliceMut<'_, Self::Item> {
953        // SAFETY:
954        // - len is valid for this slice
955        // - The returned lifetime is bound to self
956        unsafe { SliceMut::from_slice(self.slice, self.len) }
957    }
958}