pub struct Soa<T>where
T: Soars,{ /* private fields */ }
Expand description
A growable array type that stores the values for each field of T
contiguously.
The design for SoA aligns closely with Vec
:
- Overallocates capacity to provide O(1) amortized insertion
- Does not allocate until elements are added
- Never deallocates memory unless explicitly requested
- Uses
usize::MAX
as the capacity for zero-sized types
See the top-level soa_rs
docs for usage examples.
Implementations§
Source§impl<T> Soa<T>where
T: Soars,
impl<T> Soa<T>where
T: Soars,
Sourcepub fn new() -> Self
pub fn new() -> Self
Constructs a new, empty Soa<T>
.
The container will not allocate until elements are pushed onto it.
§Examples
let mut soa = Soa::<Foo>::new();
Sourcepub fn with_capacity(capacity: usize) -> Self
pub fn with_capacity(capacity: usize) -> Self
Construct a new, empty Soa<T>
with at least the specified capacity.
The container will be able to hold capacity
elements without
reallocating. If the capacity
is 0, the container will not allocate.
Note that although the returned vector has the minimum capacity
specified, the vector will have a zero length. The capacity will be as
specified unless T
is zero-sized, in which case the capacity will be
usize::MAX
.
§Examples
#[derive(Soars)]
struct Foo(u8, u8);
let mut soa = Soa::<Foo>::with_capacity(10);
assert_eq!(soa.len(), 0);
assert_eq!(soa.capacity(), 10);
// These pushes do not reallocate...
for i in 0..10 {
soa.push(Foo(i, i));
}
assert_eq!(soa.len(), 10);
assert_eq!(soa.capacity(), 10);
// ...but this one does
soa.push(Foo(11, 11));
assert_eq!(soa.len(), 11);
assert_eq!(soa.capacity(), 20);
#[derive(Soars, Copy, Clone)]
struct Bar;
// A SOA of a zero-sized type always over-allocates
let soa = Soa::<Bar>::with_capacity(10);
assert_eq!(soa.capacity(), usize::MAX);
Sourcepub fn with(element: T) -> Self
pub fn with(element: T) -> Self
Constructs a new Soa<T>
with the given first element.
This is mainly useful to get around type inference limitations in some
situations, namely macros. Type inference can struggle sometimes due to
dereferencing to an associated type of T
, which causes Rust to get
confused about whether, for example, push
ing and element should coerce
self
to the argument’s type.
§Examples
let soa = Soa::with(Foo(10));
assert_eq!(soa, soa![Foo(10)]);
Sourcepub fn capacity(&self) -> usize
pub fn capacity(&self) -> usize
Returns the total number of elements the container can hold without reallocating.
§Examples
let mut soa = Soa::<Foo>::new();
for i in 0..42 {
assert!(soa.capacity() >= i);
soa.push(Foo(i));
}
Sourcepub fn into_raw_parts(self) -> (NonNull<u8>, usize, usize)
pub fn into_raw_parts(self) -> (NonNull<u8>, usize, usize)
Decomposes a Soa<T>
into its raw components.
Returns the raw pointer to the underlying data, the length of the vector (in
elements), and the allocated capacity of the data (in elements). These
are the same arguments in the same order as the arguments to
Soa::from_raw_parts
.
After calling this function, the caller is responsible for the memory
previously managed by the Soa
. The only way to do this is to convert the
raw pointer, length, and capacity back into a Vec with the
Soa::from_raw_parts
function, allowing the destructor to perform the cleanup.
§Examples
let soa = soa![Foo(1), Foo(2)];
let (ptr, len, cap) = soa.into_raw_parts();
let rebuilt = unsafe { Soa::<Foo>::from_raw_parts(ptr, len, cap) };
assert_eq!(rebuilt, soa![Foo(1), Foo(2)]);
Sourcepub unsafe fn from_raw_parts(
ptr: NonNull<u8>,
length: usize,
capacity: usize,
) -> Self
pub unsafe fn from_raw_parts( ptr: NonNull<u8>, length: usize, capacity: usize, ) -> Self
Creates a Soa<T>
from a pointer, a length, and a capacity.
§Safety
This is highly unsafe due to the number of invariants that aren’t
checked. Given that many of these invariants are private implementation
details of [SoaRaw
], it is better not to uphold them manually. Rather,
it only valid to call this method with the output of a previous call to
Soa::into_raw_parts
.
Sourcepub fn push(&mut self, element: T)
pub fn push(&mut self, element: T)
Appends an element to the back of a collection.
§Examples
let mut soa = soa![Foo(1), Foo(2)];
soa.push(Foo(3));
assert_eq!(soa, soa![Foo(1), Foo(2), Foo(3)]);
Sourcepub fn insert(&mut self, index: usize, element: T)
pub fn insert(&mut self, index: usize, element: T)
Inserts an element at position index
, shifting all elements after it
to the right.
§Panics
Panics if index > len
§Examples
let mut soa = soa![Foo(1), Foo(2), Foo(3)];
soa.insert(1, Foo(4));
assert_eq!(soa, soa![Foo(1), Foo(4), Foo(2), Foo(3)]);
soa.insert(4, Foo(5));
assert_eq!(soa, soa![Foo(1), Foo(4), Foo(2), Foo(3), Foo(5)]);
Sourcepub fn remove(&mut self, index: usize) -> T
pub fn remove(&mut self, index: usize) -> T
Removes and returns the element at position index within the vector, shifting all elements after it to the left.
§Examples
let mut soa = soa![Foo(1), Foo(2), Foo(3)];
assert_eq!(soa.remove(1), Foo(2));
assert_eq!(soa, soa![Foo(1), Foo(3)])
Sourcepub fn reserve(&mut self, additional: usize)
pub fn reserve(&mut self, additional: usize)
Reserves capacity for at least additional more elements to be inserted
in the given Soa<T>
. The collection may reserve more space to
speculatively avoid frequent reallocations. After calling reserve,
capacity will be greater than or equal to self.len() + additional
.
Does nothing if capacity is already sufficient.
§Examples
let mut soa = soa![Foo(1)];
soa.reserve(10);
assert!(soa.capacity() >= 11);
Sourcepub fn reserve_exact(&mut self, additional: usize)
pub fn reserve_exact(&mut self, additional: usize)
Reserves the minimum capacity for at least additional more elements to
be inserted in the given Soa<T>
. Unlike Soa::reserve
, this will
not deliberately over-allocate to speculatively avoid frequent
allocations. After calling reserve_exact
, capacity will be equal to
self.len() + additional, or else usize::MAX
if T
is zero-sized. Does
nothing if the capacity is already sufficient.
§Examples
let mut soa = soa![Foo(1)];
soa.reserve(10);
assert!(soa.capacity() == 11);
Sourcepub fn shrink_to_fit(&mut self)
pub fn shrink_to_fit(&mut self)
Shrinks the capacity of the container as much as possible.
§Examples
let mut soa = Soa::<Foo>::with_capacity(10);
soa.extend([Foo(1), Foo(2), Foo(3)]);
assert_eq!(soa.capacity(), 10);
soa.shrink_to_fit();
assert_eq!(soa.capacity(), 3);
Sourcepub fn shrink_to(&mut self, min_capacity: usize)
pub fn shrink_to(&mut self, min_capacity: usize)
Shrinks the capacity of the vector with a lower bound.
The capacity will remain at least as large as both the length and the supplied value. If the current capacity is less than the lower limit, this is a no-op.
§Examples
let mut soa = Soa::<Foo>::with_capacity(10);
soa.extend([Foo(1), Foo(2), Foo(3)]);
assert_eq!(soa.capacity(), 10);
soa.shrink_to(4);
assert_eq!(soa.capacity(), 4);
soa.shrink_to(0);
assert_eq!(soa.capacity(), 3);
Sourcepub fn truncate(&mut self, len: usize)
pub fn truncate(&mut self, len: usize)
Shortens the vector, keeping the first len elements and dropping the rest.
If len is greater or equal to the vector’s current length, this has no effect. Note that this method has no effect on the allocated capacity of the vector.
§Examples
Truncating a five-element SOA to two elements:
let mut soa = soa![Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)];
soa.truncate(2);
assert_eq!(soa, soa![Foo(1), Foo(2)]);
No truncation occurs when len
is greater than the SOA’s current
length:
let mut soa = soa![Foo(1), Foo(2), Foo(3)];
soa.truncate(8);
assert_eq!(soa, soa![Foo(1), Foo(2), Foo(3)]);
Truncating with len == 0
is equivalent to Soa::clear
.
let mut soa = soa![Foo(1), Foo(2), Foo(3)];
soa.truncate(0);
assert_eq!(soa, soa![]);
Sourcepub fn swap_remove(&mut self, index: usize) -> T
pub fn swap_remove(&mut self, index: usize) -> T
Removes an element from the vector and returns it.
The removed element is replaced by the last element of the vector. This does not preserve ordering, but is O(1). If you need to preserve the element order, use remove instead.
§Panics
Panics if index is out of bounds.
§Examples
let mut soa = soa![Foo(0), Foo(1), Foo(2), Foo(3)];
assert_eq!(soa.swap_remove(1), Foo(1));
assert_eq!(soa, soa![Foo(0), Foo(3), Foo(2)]);
assert_eq!(soa.swap_remove(0), Foo(0));
assert_eq!(soa, soa![Foo(2), Foo(3)])
Sourcepub fn append(&mut self, other: &mut Self)
pub fn append(&mut self, other: &mut Self)
Moves all the elements of other into self, leaving other empty.
§Examples
let mut soa1 = soa![Foo(1), Foo(2), Foo(3)];
let mut soa2 = soa![Foo(4), Foo(5), Foo(6)];
soa1.append(&mut soa2);
assert_eq!(soa1, soa![Foo(1), Foo(2), Foo(3), Foo(4), Foo(5), Foo(6)]);
assert_eq!(soa2, soa![]);
Methods from Deref<Target = Slice<T>>§
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of elements in the slice, also referred to as its length.
§Examples
let soa = soa![Foo(1), Foo(2), Foo(3)];
assert_eq!(soa.len(), 3);
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if the slice contains no elements.
§Examples
let mut soa = Soa::<Foo>::new();
assert!(soa.is_empty());
soa.push(Foo(1));
assert!(!soa.is_empty());
Sourcepub fn iter(&self) -> Iter<'_, T> ⓘ
pub fn iter(&self) -> Iter<'_, T> ⓘ
Returns an iterator over the elements.
The iterator yields all items from start to end.
§Examples
let soa = soa![Foo(1), Foo(2), Foo(4)];
let mut iter = soa.iter();
assert_eq!(iter.next(), Some(FooRef(&1)));
assert_eq!(iter.next(), Some(FooRef(&2)));
assert_eq!(iter.next(), Some(FooRef(&4)));
assert_eq!(iter.next(), None);
Sourcepub fn iter_mut(&mut self) -> IterMut<'_, T> ⓘ
pub fn iter_mut(&mut self) -> IterMut<'_, T> ⓘ
Returns an iterator over the elements that allows modifying each value.
The iterator yields all items from start to end.
§Examples
let mut soa = soa![Foo(1), Foo(2), Foo(4)];
for mut elem in soa.iter_mut() {
*elem.0 *= 2;
}
assert_eq!(soa, soa![Foo(2), Foo(4), Foo(8)]);
Sourcepub fn get<I>(&self, index: I) -> Option<I::Output<'_>>where
I: SoaIndex<T>,
pub fn get<I>(&self, index: I) -> Option<I::Output<'_>>where
I: SoaIndex<T>,
Returns a reference to an element or subslice depending on the type of index.
-
If given a position, returns a reference to the element at that position or None if out of bounds.
-
If given a range, returns the subslice corresponding to that range, or None if out of bounds.
§Examples
let soa = soa![Foo(10), Foo(40), Foo(30), Foo(20)];
assert_eq!(soa.get(1), Some(FooRef(&40)));
assert!(soa.get(4).is_none());
assert_eq!(soa.get(..), Some(soa![Foo(10), Foo(40), Foo(30), Foo(20)].as_slice()));
assert_eq!(soa.get(..2), Some(soa![Foo(10), Foo(40)].as_slice()));
assert_eq!(soa.get(..=2), Some(soa![Foo(10), Foo(40), Foo(30)].as_slice()));
assert_eq!(soa.get(2..), Some(soa![Foo(30), Foo(20)].as_slice()));
assert_eq!(soa.get(1..3), Some(soa![Foo(40), Foo(30)].as_slice()));
assert_eq!(soa.get(1..=3), Some(soa![Foo(40), Foo(30), Foo(20)].as_slice()));
assert!(soa.get(2..5).is_none());
Sourcepub fn idx<I>(&self, index: I) -> I::Output<'_>where
I: SoaIndex<T>,
pub fn idx<I>(&self, index: I) -> I::Output<'_>where
I: SoaIndex<T>,
Returns a reference to the element at the given index.
This is similar to Index
, which is not implementable for this type.
See get
for a non-panicking version.
§Panics
Panics if the index is out-of-bounds, which is whenever
SoaIndex::get
returns None
.
§Examples
let soa = soa![Foo(10), Foo(40), Foo(30), Foo(90)];
assert_eq!(soa.idx(3), FooRef(&90));
assert_eq!(soa.idx(1..3), soa![Foo(40), Foo(30)]);
Sourcepub fn idx_mut<I>(&mut self, index: I) -> I::OutputMut<'_>where
I: SoaIndex<T>,
pub fn idx_mut<I>(&mut self, index: I) -> I::OutputMut<'_>where
I: SoaIndex<T>,
Returns a mutable reference to the element at the given index.
This is similar to IndexMut
, which is not implementable for this
type. See get_mut
for a non-panicking version.
§Panics
Panics if the index is out-of-bounds, which is whenever
SoaIndex::get_mut
returns None
.
§Examples
let mut soa = soa![Foo(10), Foo(20), Foo(30)];
*soa.idx_mut(1).0 = 42;
assert_eq!(soa, soa![Foo(10), Foo(42), Foo(30)]);
Sourcepub fn swap(&mut self, a: usize, b: usize)
pub fn swap(&mut self, a: usize, b: usize)
Swaps the position of two elements.
§Arguments
a
: The index of the first elementb
: The index of the second element
§Panics
Panics if a
or b
is out of bounds.
§Examples
let mut soa = soa![Foo(0), Foo(1), Foo(2), Foo(3), Foo(4)];
soa.swap(2, 4);
assert_eq!(soa, soa![Foo(0), Foo(1), Foo(4), Foo(3), Foo(2)]);
Sourcepub fn first(&self) -> Option<T::Ref<'_>>
pub fn first(&self) -> Option<T::Ref<'_>>
Returns the first element of the slice, or None if empty.
§Examples
let soa = soa![Foo(10), Foo(40), Foo(30)];
assert_eq!(soa.first(), Some(FooRef(&10)));
let soa = Soa::<Foo>::new();
assert_eq!(soa.first(), None);
Sourcepub fn first_mut(&mut self) -> Option<T::RefMut<'_>>
pub fn first_mut(&mut self) -> Option<T::RefMut<'_>>
Returns a mutable reference to the first element of the slice, or None if empty.
§Examples
let mut soa = soa![Foo(0), Foo(1), Foo(2)];
if let Some(mut first) = soa.first_mut() {
*first.0 = 5;
}
assert_eq!(soa, soa![Foo(5), Foo(1), Foo(2)]);
Sourcepub fn last(&self) -> Option<T::Ref<'_>>
pub fn last(&self) -> Option<T::Ref<'_>>
Returns the last element of the slice, or None if empty.
§Examples
let soa = soa![Foo(10), Foo(40), Foo(30)];
assert_eq!(soa.last(), Some(FooRef(&30)));
let soa = Soa::<Foo>::new();
assert_eq!(soa.last(), None);
Sourcepub fn last_mut(&mut self) -> Option<T::RefMut<'_>>
pub fn last_mut(&mut self) -> Option<T::RefMut<'_>>
Returns a mutable reference to the last element of the slice, or None if empty.
§Examples
let mut soa = soa![Foo(0), Foo(1), Foo(2)];
if let Some(mut last) = soa.last_mut() {
*last.0 = 5;
}
assert_eq!(soa, soa![Foo(0), Foo(1), Foo(5)]);
Sourcepub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> ⓘ
pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> ⓘ
Returns an iterator over chunk_size
elements of the slice at a time,
starting at the beginning of the slice.
The chunks are slices and do not overlap. If chunk_size
does not divide
the length of the slice, then the last up to chunk_size-1
elements will
be omitted and can be retrieved from the remainder
function of the
iterator.
Due to each chunk having exactly chunk_size
elements, the compiler can
often optimize the resulting code better than in the case of chunks.
§Examples
let soa = soa![Foo('l'), Foo('o'), Foo('r'), Foo('e'), Foo('m')];
let mut iter = soa.chunks_exact(2);
assert_eq!(iter.next(), Some(soa![Foo('l'), Foo('o')].as_slice()));
assert_eq!(iter.next(), Some(soa![Foo('r'), Foo('e')].as_slice()));
assert!(iter.next().is_none());
assert_eq!(iter.remainder(), &soa![Foo('m')]);
Sourcepub fn slices(&self) -> T::Slices<'_>
pub fn slices(&self) -> T::Slices<'_>
Returns a collection of slices for each field of the slice.
For convenience, slices can also be aquired using the getter methods for individual fields.
§Examples
let soa = soa![Foo { foo: 1, bar: 2 }, Foo { foo: 3, bar: 4 }];
let slices = soa.slices();
assert_eq!(slices.foo, soa.foo());
assert_eq!(slices.bar, soa.bar());
Sourcepub fn slices_mut(&mut self) -> T::SlicesMut<'_>
pub fn slices_mut(&mut self) -> T::SlicesMut<'_>
Returns a collection of mutable slices for each field of the slice.
For convenience, individual mutable slices can also be aquired using the getter methods for individual fields. This method is necessary to be able to mutably borrow multiple SoA fields simultaneously.
§Examples
let mut soa = soa![Foo { foo: 1, bar: 0 }, Foo { foo: 2, bar: 0 }];
let slices = soa.slices_mut();
for (foo, bar) in slices.foo.iter().zip(slices.bar) {
*bar = foo * 2;
}
assert_eq!(soa.bar(), [2, 4]);
Trait Implementations§
Source§impl<T> AsMutSlice for Soa<T>where
T: Soars,
impl<T> AsMutSlice for Soa<T>where
T: Soars,
Source§impl<T> BorrowMut<Slice<T>> for Soa<T>where
T: Soars,
impl<T> BorrowMut<Slice<T>> for Soa<T>where
T: Soars,
Source§fn borrow_mut(&mut self) -> &mut Slice<T>
fn borrow_mut(&mut self) -> &mut Slice<T>
Source§impl<T> Extend<T> for Soa<T>where
T: Soars,
impl<T> Extend<T> for Soa<T>where
T: Soars,
Source§fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)