soapy/
lib.rs

1//! # Soapy
2//!
3//! Soapy 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 [`Soapy`] for your type:
9//! ```
10//! # use soapy::{soa, Soapy};
11//! #[derive(Soapy, 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 soapy::{soa, Soapy, Soa};
22//! # #[derive(Soapy, 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 soapy::{soa, Soapy};
35//! # #[derive(Soapy, 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 soapy::{soa, Soapy};
48//! # #[derive(Soapy, 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), Example { foo: 7, bar: 8 });
61//! assert_eq!(soa.idx(1..3), [Example { foo: 3, bar: 4 }, Example { foo: 5, bar: 6 }]);
62//! ```
63//!
64//! The usual [`Vec`] APIs work normally.
65//! ```
66//! # use soapy::{soa, Soapy, Soa};
67//! # #[derive(Soapy, Debug, Clone, Copy, PartialEq)]
68//! # #[soa_derive(Debug, PartialEq)]
69//! # struct Example {
70//! #     foo: u8,
71//! #     bar: u16,
72//! # }
73//! let mut soa = Soa::<Example>::new();
74//! soa.push(Example { foo: 1, bar: 2 });
75//! soa.push(Example { foo: 3, bar: 4 });
76//! soa.insert(0, Example { foo: 5, bar: 6 });
77//! assert_eq!(soa.pop(), Some(Example { foo: 3, bar: 4 }));
78//! for mut el in &mut soa {
79//!     *el.bar += 10;
80//! }
81//! assert_eq!(soa.bar(), [16, 12]);
82//! ```
83//!
84//! # Field getters
85//!
86//! You can access the fields as slices.
87//! ```
88//! # use soapy::{soa, Soapy};
89//! # #[derive(Soapy, Debug, Clone, Copy, PartialEq)]
90//! # #[soa_derive(Debug, PartialEq)]
91//! # struct Example {
92//! #     foo: u8,
93//! #     bar: u16,
94//! # }
95//! let mut soa = soa![
96//!     Example { foo: 1, bar: 2 },
97//!     Example { foo: 3, bar: 4 },
98//! ];
99//! assert_eq!(soa.foo(), [1, 3]);
100//! ```
101//!
102//! Postpend `_mut` for mutable slices.
103//! ```
104//! # use soapy::{soa, Soapy};
105//! # #[derive(Soapy, Debug, Clone, Copy, PartialEq)]
106//! # #[soa_derive(Debug, PartialEq)]
107//! # struct Example {
108//! #     foo: u8,
109//! #     bar: u16,
110//! # }
111//! # let mut soa = soa![
112//! #     Example { foo: 1, bar: 2 },
113//! #     Example { foo: 3, bar: 4 },
114//! # ];
115//! for foo in soa.foo_mut() {
116//!     *foo += 10;
117//! }
118//! assert_eq!(soa.foo(), [11, 13]);
119//! ```
120//!
121//! For tuple structs, prepend the field number with `f`:
122//! ```
123//! # use soapy::{soa, Soapy};
124//! #[derive(Soapy)]
125//! # #[soa_derive(Debug, PartialEq)]
126//! struct Example(u8);
127//! let soa = soa![Example(5), Example(10)];
128//! assert_eq!(soa.f0(), [5, 10]);
129//! ```
130//!
131//! [`Soapy`]: soapy_derive::Soapy
132#![warn(missing_docs)]
133
134mod soa;
135pub use soa::Soa;
136
137mod index;
138pub use index::SoaIndex;
139
140mod into_iter;
141pub use into_iter::IntoIter;
142
143mod iter;
144pub use iter::Iter;
145
146mod iter_mut;
147pub use iter_mut::IterMut;
148
149mod slice;
150pub use slice::Slice;
151
152mod slice_mut;
153pub use slice_mut::SliceMut;
154
155mod slice_ref;
156pub use slice_ref::SliceRef;
157
158mod soa_deref;
159pub use soa_deref::SoaDeref;
160
161mod soapy;
162pub use soapy::Soapy;
163
164mod soa_raw;
165#[doc(hidden)]
166pub use soa_raw::SoaRaw;
167
168mod chunks_exact;
169pub use chunks_exact::ChunksExact;
170
171mod eq_impl;
172mod iter_raw;
173
174mod soa_array;
175pub use soa_array::SoaArray;
176
177mod as_soa_ref;
178pub use as_soa_ref::AsSoaRef;
179
180/// Derive macro for the [`Soapy`] trait.
181///
182/// Deriving Soapy for some struct `Foo` will create the following additional
183/// structs:
184///
185/// | Struct         | Field type | Use                                          |
186/// |----------------|------------|----------------------------------------------|
187/// | `FooSoaRaw`    | `*mut T`   | Low-level, unsafe memory handling for SoA    |
188/// | `FooRef`       | `&T`       | SoA element reference                        |
189/// | `FooRefMut`    | `&mut T`   | Mutable SoA element reference                |
190/// | `FooSlices`    | `&[T]`     | SoA fields                                   |
191/// | `FooSlicesMut` | `&mut [T]` | Mutable SoA fields                           |
192/// | `FooArray`     | `[T; N]`   | `const`-compatible SoA                       |
193/// | `FooDeref`     |            | SoA [`Deref`] target, provides slice getters |
194///
195/// The [`Soapy`] trait implementation for `Foo` references these as associated
196/// types. [`AsSoaRef`] is also implemented for `Foo`, `FooRef`, and `FooRefMut`.
197///
198/// # Derive for generated types
199///
200/// The `soa_derive` attribute can be used to derive traits for the generated
201/// types. In the example, `Debug` and `PartialEq` will be implemented for
202/// `FooRef`, `FooRefMut`, `FooSlices`, `FooSlicesMut`, and `FooArray`.
203///
204/// ```
205/// # use soapy::{Soapy};
206/// #[derive(Soapy)]
207/// #[soa_derive(Debug, PartialEq)]
208/// struct Foo(u8);
209/// assert_eq!(FooRef(&10), FooRef(&10));
210/// ```
211///
212/// # Alignment
213///
214/// Individual fields can be tagged with the `align` attribute to raise their
215/// alignment. The slice for that field will start at a multiple of the
216/// requested alignment if it is greater than or equal to the alignment of the
217/// field's type. This can be useful for vector operations.
218///
219/// ```
220/// # use soapy::{Soapy};
221/// # #[derive(Soapy)]
222/// # #[soa_derive(Debug, PartialEq)]
223/// struct Foo(#[align(8)] u8);
224/// ```
225///
226/// [`Deref`]: std::ops::Deref
227pub use soapy_derive::Soapy;
228
229/// Creates a [`Soa`] containing the arguments.
230///
231/// `soa!` allows [`Soa`]s to be defined with the same syntax as array
232/// expressions. There are two forms of this macro:
233///
234/// - Create a [`Soa`] containing a given list of elements:
235/// ```
236/// # use soapy::{Soapy, soa};
237/// # #[derive(Soapy, Debug, PartialEq, Copy, Clone)]
238/// # #[soa_derive(Debug, PartialEq, PartialOrd)]
239/// # struct Foo(u8, u16);
240/// let soa = soa![Foo(1, 2), Foo(3, 4)];
241/// assert_eq!(soa, [Foo(1, 2), Foo(3, 4)]);
242/// ```
243///
244/// - Create a [`Soa`] from a given element and size:
245///
246/// ```
247/// # use soapy::{Soapy, soa};
248/// # #[derive(Soapy, Debug, PartialEq, Copy, Clone)]
249/// # #[soa_derive(Debug, PartialEq)]
250/// # struct Foo(u8, u16);
251/// let soa = soa![Foo(1, 2); 2];
252/// assert_eq!(soa, [Foo(1, 2); 2]);
253/// ```
254#[macro_export]
255macro_rules! soa {
256    () => {
257        $crate::Soa::new()
258    };
259
260    ($x:expr $(,$xs:expr)* $(,)?) => {
261        {
262            let mut out = $crate::Soa::with($x);
263            $(
264            out.push($xs);
265            )*
266            out
267        }
268    };
269
270    ($elem:expr; 0) => {
271        soa![]
272    };
273
274    ($elem:expr; 1) => {
275        $crate::Soa::with($elem)
276    };
277
278    ($elem:expr; $n:expr) => {
279        {
280            let elem = $elem;
281            let mut out = $crate::Soa::with(elem.clone());
282
283            let mut i = 2;
284            while i < $n {
285                out.push(elem.clone());
286            }
287
288            out.push(elem);
289            out
290        }
291    };
292}
293
294#[doc = include_str!("../README.md")]
295mod readme_tests {}
296
297mod borrow_tests;