soa_rs/
lib.rs

1//! # Soars
2//!
3//! Soars makes it simple to work with the structure-of-arrays memory layout.
4//! What [`Vec`] is to array-of-structures, [`Soa`] is to structure-of-arrays.
5//!
6//! # Examples
7//!
8//! First, derive [`Soars`] for your type:
9//! ```
10//! # use soa_rs::{soa, Soars};
11//! #[derive(Soars, Debug, Clone, Copy, PartialEq)]
12//! #[soa_derive(Debug, PartialEq)]
13//! struct Example {
14//!     foo: u8,
15//!     bar: u16,
16//! }
17//! ```
18//!
19//! You can create an [`Soa`] explicitly:
20//! ```
21//! # use soa_rs::{soa, Soars, Soa};
22//! # #[derive(Soars, Debug, Clone, Copy, PartialEq)]
23//! # #[soa_derive(Debug, PartialEq)]
24//! # struct Example {
25//! #     foo: u8,
26//! #     bar: u16,
27//! # }
28//! let mut soa: Soa<Example> = Soa::new();
29//! soa.push(Example { foo: 1, bar: 2 });
30//! ```
31//!
32//! ...or by using the [`soa!`] macro.
33//! ```
34//! # use soa_rs::{soa, Soars};
35//! # #[derive(Soars, Debug, Clone, Copy, PartialEq)]
36//! # #[soa_derive(Debug, PartialEq)]
37//! # struct Example {
38//! #     foo: u8,
39//! #     bar: u16,
40//! # }
41//! let mut soa = soa![Example { foo: 1, bar: 2 }, Example { foo: 3, bar: 4 }];
42//! ```
43//!
44//! An SoA can be indexed and sliced just like a `&[T]`. Use `idx` in lieu of
45//! the index operator.
46//! ```
47//! # use soa_rs::{soa, Soars, AsSlice};
48//! # #[derive(Soars, Debug, Clone, Copy, PartialEq)]
49//! # #[soa_derive(Debug, PartialEq)]
50//! # struct Example {
51//! #     foo: u8,
52//! #     bar: u16,
53//! # }
54//! let mut soa = soa![
55//!     Example { foo: 1, bar: 2 },
56//!     Example { foo: 3, bar: 4 },
57//!     Example { foo: 5, bar: 6 },
58//!     Example { foo: 7, bar: 8 }
59//! ];
60//! assert_eq!(soa.idx(3), ExampleRef { foo: &7, bar: &8 });
61//! assert_eq!(
62//!     soa.idx(1..3),
63//!     soa![
64//!         Example { foo: 3, bar: 4 },
65//!         Example { foo: 5, bar: 6 },
66//!     ],
67//! );
68//! ```
69//!
70//! The usual [`Vec`] APIs work normally.
71//! ```
72//! # use soa_rs::{soa, Soars, Soa};
73//! # #[derive(Soars, Debug, Clone, Copy, PartialEq)]
74//! # #[soa_derive(Debug, PartialEq)]
75//! # struct Example {
76//! #     foo: u8,
77//! #     bar: u16,
78//! # }
79//! let mut soa = Soa::<Example>::new();
80//! soa.push(Example { foo: 1, bar: 2 });
81//! soa.push(Example { foo: 3, bar: 4 });
82//! soa.insert(0, Example { foo: 5, bar: 6 });
83//! assert_eq!(soa.pop(), Some(Example { foo: 3, bar: 4 }));
84//! for mut el in &mut soa {
85//!     *el.bar += 10;
86//! }
87//! assert_eq!(soa.bar(), [16, 12]);
88//! ```
89//!
90//! # Field getters
91//!
92//! You can access the fields as slices.
93//! ```
94//! # use soa_rs::{soa, Soars};
95//! # #[derive(Soars, Debug, Clone, Copy, PartialEq)]
96//! # #[soa_derive(Debug, PartialEq)]
97//! # struct Example {
98//! #     foo: u8,
99//! #     bar: u16,
100//! # }
101//! let mut soa = soa![
102//!     Example { foo: 1, bar: 2 },
103//!     Example { foo: 3, bar: 4 },
104//! ];
105//! assert_eq!(soa.foo(), [1, 3]);
106//! ```
107//!
108//! Postpend `_mut` for mutable slices.
109//! ```
110//! # use soa_rs::{soa, Soars};
111//! # #[derive(Soars, Debug, Clone, Copy, PartialEq)]
112//! # #[soa_derive(Debug, PartialEq)]
113//! # struct Example {
114//! #     foo: u8,
115//! #     bar: u16,
116//! # }
117//! # let mut soa = soa![
118//! #     Example { foo: 1, bar: 2 },
119//! #     Example { foo: 3, bar: 4 },
120//! # ];
121//! for foo in soa.foo_mut() {
122//!     *foo += 10;
123//! }
124//! assert_eq!(soa.foo(), [11, 13]);
125//! ```
126//!
127//! For tuple structs, prepend the field number with `f`:
128//! ```
129//! # use soa_rs::{soa, Soars};
130//! #[derive(Soars)]
131//! # #[soa_derive(Debug, PartialEq)]
132//! struct Example(u8);
133//! let soa = soa![Example(5), Example(10)];
134//! assert_eq!(soa.f0(), [5, 10]);
135//! ```
136//!
137//! # Serde
138//!
139//! [`serde`](https://serde.rs/) support is enabled by the `serde` feature
140//! flag.
141//!
142//! ```ignore
143//! #[derive(Soars, serde::Deserialize)]
144//! #[soa_derive(include(Ref), serde::Serialize)]
145//! struct Test(u32);
146//! ```
147//!
148//! [`Soars`]: soa_rs_derive::Soars
149#![warn(missing_docs)]
150
151mod soa;
152pub use soa::Soa;
153
154mod index;
155pub use index::SoaIndex;
156
157mod into_iter;
158pub use into_iter::IntoIter;
159
160mod iter;
161pub use iter::Iter;
162
163mod iter_mut;
164pub use iter_mut::IterMut;
165
166mod slice;
167pub use slice::Slice;
168
169mod slice_mut;
170pub use slice_mut::SliceMut;
171
172mod slice_ref;
173pub use slice_ref::SliceRef;
174
175mod soa_deref;
176pub use soa_deref::SoaDeref;
177
178mod soars;
179pub use soars::Soars;
180
181mod soa_raw;
182#[doc(hidden)]
183pub use soa_raw::SoaRaw;
184
185mod chunks_exact;
186pub use chunks_exact::ChunksExact;
187
188mod iter_raw;
189
190mod as_slice;
191pub use as_slice::{AsMutSlice, AsSlice};
192
193mod as_soa_ref;
194pub use as_soa_ref::AsSoaRef;
195
196#[cfg(feature = "serde")]
197mod serde;
198
199/// Derive macro for the [`Soars`] trait.
200///
201/// Deriving Soars for some struct `Foo` will create the following additional
202/// structs:
203///
204/// | Struct         | Field type | Use                                          |
205/// |----------------|------------|----------------------------------------------|
206/// | `FooSoaRaw`    | `*mut T`   | Low-level, unsafe memory handling for SoA    |
207/// | `FooRef`       | `&T`       | SoA element reference                        |
208/// | `FooRefMut`    | `&mut T`   | Mutable SoA element reference                |
209/// | `FooSlices`    | `&[T]`     | SoA fields                                   |
210/// | `FooSlicesMut` | `&mut [T]` | Mutable SoA fields                           |
211/// | `FooArray`     | `[T; N]`   | `const`-compatible SoA                       |
212/// | `FooDeref`     |            | SoA [`Deref`] target, provides slice getters |
213///
214/// The [`Soars`] trait implementation for `Foo` references these as associated
215/// types. [`AsSoaRef`] is also implemented for `Foo`, `FooRef`, and `FooRefMut`.
216///
217/// # Arrays
218///
219/// The `FooArray` type is only generated when the `#[soa_array]` attribute is
220/// added to the struct. Only structs without interior mutability support this
221/// attribute for the time being, due to [this
222/// issue](https://github.com/rust-lang/rust/issues/80384). SOA array types are
223/// stack-allocated like normal arrays and are `const`-initializable.
224///
225/// # Derive for generated types
226///
227/// The `soa_derive` attribute can be used to derive traits for the generated
228/// types. `Copy` and `Clone` are added automatically for `FooRef` and
229/// `FooSlices`. In the following example, we have the following trait
230/// implementations:
231///
232/// | Struct         | `Copy`/`Clone` | `Debug`/`PartialEq` | `Eq` | `PartialOrd` |
233/// |----------------|----------------|---------------------|------|--------------|
234/// | `FooRef`       | ✅             | ✅                  | ✅   |              |
235/// | `FooRefMut`    |                | ✅                  | ✅   | ✅           |
236/// | `FooSlices`    | ✅             | ✅                  |      |              |
237/// | `FooSlicesMut` |                | ✅                  |      | ✅           |
238/// | `FooArray`     |                | ✅                  |      | ✅           |
239///
240/// ```
241/// # use soa_rs::{Soars};
242/// #[derive(Soars)]
243/// #[soa_derive(Debug, PartialEq)]
244/// #[soa_derive(include(Ref, RefMut), Eq)]
245/// #[soa_derive(exclude(Ref, Slices), PartialOrd)]
246/// struct Foo(u8);
247/// ```
248///
249/// # Alignment
250///
251/// Individual fields can be tagged with the `align` attribute to raise their
252/// alignment. The slice for that field will start at a multiple of the
253/// requested alignment if it is greater than or equal to the alignment of the
254/// field's type. This can be useful for vector operations.
255///
256/// ```
257/// # use soa_rs::{Soars};
258/// # #[derive(Soars)]
259/// # #[soa_derive(Debug, PartialEq)]
260/// struct Foo(#[align(8)] u8);
261/// ```
262///
263/// [`Deref`]: std::ops::Deref
264pub use soa_rs_derive::Soars;
265
266/// Creates a [`Soa`] containing the arguments.
267///
268/// `soa!` allows [`Soa`]s to be defined with the same syntax as array
269/// expressions. There are two forms of this macro:
270///
271/// - Create a [`Soa`] containing a given list of elements:
272/// ```
273/// # use soa_rs::{Soars, soa};
274/// # #[derive(Soars, Debug, PartialEq, Copy, Clone)]
275/// # #[soa_derive(Debug, PartialEq, PartialOrd)]
276/// # struct Foo(u8, u16);
277/// let soa = soa![Foo(1, 2), Foo(3, 4)];
278/// assert_eq!(soa, soa![Foo(1, 2), Foo(3, 4)]);
279/// ```
280///
281/// - Create a [`Soa`] from a given element and size:
282///
283/// ```
284/// # use soa_rs::{Soars, soa};
285/// # #[derive(Soars, Debug, PartialEq, Copy, Clone)]
286/// # #[soa_derive(Debug, PartialEq)]
287/// # struct Foo(u8, u16);
288/// let soa = soa![Foo(1, 2); 2];
289/// assert_eq!(soa, soa![Foo(1, 2), Foo(1, 2)]);
290/// ```
291#[macro_export]
292macro_rules! soa {
293    () => {
294        $crate::Soa::new()
295    };
296
297    ($x:expr $(,$xs:expr)* $(,)?) => {
298        {
299            let mut out = $crate::Soa::with($x);
300            $(
301            out.push($xs);
302            )*
303            out
304        }
305    };
306
307    ($elem:expr; 0) => {
308        soa![]
309    };
310
311    ($elem:expr; 1) => {
312        $crate::Soa::with($elem)
313    };
314
315    ($elem:expr; $n:expr) => {
316        {
317            let elem = $elem;
318            let mut out = $crate::Soa::with(elem.clone());
319
320            let mut i = 2;
321            while i < $n {
322                out.push(elem.clone());
323            }
324
325            out.push(elem);
326            out
327        }
328    };
329}
330
331#[doc = include_str!("../README.md")]
332mod readme_tests {}
333
334mod borrow_tests;