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}