#[derive(Soa)]
{
// Attributes available to this derive:
#[soa]
}
Expand description
Build a fixed sized SoA (Structure of Arrays) from a struct. The outputted SoA will be suitable for in place storage in messages and should be easier for the compiler to vectorize.
for example:
#[derive(Soa)]
struct MyStruct {
a: i32,
b: f32,
}will generate:
pub struct MyStructSoa<const N: usize> {
pub a: [i32; N],
pub b: [f32; N],
}You can then use the generated struct to store multiple instances of the original struct in an SoA format.
// makes an SOA with a default value
let soa1: MyStructSoa<8> = XyzSoa::new(MyStruct{ a: 1, b: 2.3 });Then you can access the fields of the SoA as slices:
let a = soa1.a();
let b = soa1.b();You can also access a range of the fields:
let a = soa1.a_range(0..4);
let b = soa1.b_range(0..4);You can also modify the fields of the SoA:
soa1.a_mut()[0] = 42;
soa1.b_mut()[0] = 42.0;You can also modify a range of the fields:
soa1.a_range_mut(0..4)[0] = 42;
soa1.b_range_mut(0..4)[0] = 42.0;You can also apply a function to all the fields of the SoA:
soa1.apply(|a, b| {
(a + 1, b + 1.0)
});You can also compose nested SoAs by annotating fields with #[soa(nested)]:
#[derive(Soa)]
struct ColoredPoint {
#[soa(nested)]
position: Xyz,
#[soa(nested)]
color: Color,
}
// ColoredPointSoa<N> stores position as XyzSoaStorage<N> and color as ColorSoaStorage<N>.For nested types from other crates, use absolute paths like ::other_crate::Type
so the generated storage path resolves correctly.
Type aliases are not supported for #[soa(nested)] because storage names are derived from the
final type identifier.
Bincode encoding changed: SoA fields no longer include per-field length prefixes. Old blobs are
not compatible with the new layout.
Memory layout
- Flat fields:
MyStructSoa<N>storeslenplus one[T; N]per field. - Nested fields (
#[soa(nested)]): the field is stored inline as<Field>SoaStorage<N>, so the top-level struct containslenplus nested storage(s) and the leaf arrays live in those nested storages. *SoaStorage<N>has the same layout as*Soa<N>without thelenfield.
ASCII layouts
Flat:
MyStructSoa<N>
+-----+------------------+------------------+
| len | a: [i32; N] | b: [f32; N] |
+-----+------------------+------------------+
Nested:
ColoredPointSoa<N>
+-----+---------------------+---------------------+
| len | position: XyzSoaStorage<N> | color: ColorSoaStorage<N> |
+-----+---------------------+---------------------+
| |
v v
XyzSoaStorage<N> ColorSoaStorage<N>
+------------------+ +------------------+
| x: [f32; N] | | r: [f32; N] |
| y: [f32; N] | | g: [f32; N] |
| z: [f32; N] | | b: [f32; N] |
| i: [i32; N] | +------------------+
+------------------+struct ColoredPointSoa<const N: usize> {
len: usize,
position: XyzSoaStorage<N>,
color: ColorSoaStorage<N>,
}
struct XyzSoaStorage<const N: usize> {
x: [f32; N],
y: [f32; N],
z: [f32; N],
i: [i32; N],
}