soa_derive/lib.rs
1//! This crate provides a custom derive (`#[derive(StructOfArray)]`) to
2//! automatically generate code from a given struct `T` that allow to replace
3//! `Vec<T>` with a struct of arrays. For example, the following code
4//!
5//! ```
6//! # #[macro_use] extern crate soa_derive;
7//! # mod cheese {
8//! #[derive(StructOfArray)]
9//! pub struct Cheese {
10//! pub smell: f64,
11//! pub color: (f64, f64, f64),
12//! pub with_mushrooms: bool,
13//! pub name: String,
14//! }
15//! # }
16//! ```
17//!
18//! will generate a `CheeseVec` struct that looks like this:
19//!
20//! ```
21//! pub struct CheeseVec {
22//! pub smell: Vec<f64>,
23//! pub color: Vec<(f64, f64, f64)>,
24//! pub with_mushrooms: Vec<bool>,
25//! pub name: Vec<String>,
26//! }
27//! ```
28//!
29//! It will also generate the same functions that a `Vec<Chees>` would have, and
30//! a few helper structs: `CheeseSlice`, `CheeseSliceMut`, `CheeseRef` and
31//! `CheeseRefMut` corresponding respectivly to `&[Cheese]`, `&mut [Cheese]`,
32//! `&Cheese` and `&mut Cheese`.
33//!
34//! # How to use it
35//!
36//! Add `#[derive(StructOfArray)]` to each struct you want to derive a struct of
37//! array version. If you need the helper structs to derive additional traits
38//! (such as `Debug` or `PartialEq`), you can add an attribute `#[soa_derive =
39//! "Debug, PartialEq"]` to the struct declaration.
40//!
41//! ```
42//! # #[macro_use] extern crate soa_derive;
43//! # mod cheese {
44//! #[derive(Debug, PartialEq, StructOfArray)]
45//! #[soa_derive(Debug, PartialEq)]
46//! pub struct Cheese {
47//! pub smell: f64,
48//! pub color: (f64, f64, f64),
49//! pub with_mushrooms: bool,
50//! pub name: String,
51//! }
52//! # }
53//! ```
54//!
55//! If you want to add attribute to a specific generated struct(such as
56//! `#[cfg_attr(test, derive(PartialEq))]` on `CheeseVec`), you can add an
57//! attribute `#[soa_attr(Vec, cfg_attr(test, derive(PartialEq)))]` to the
58//! struct declaration.
59//!
60//! ```
61//! # #[macro_use] extern crate soa_derive;
62//! # mod cheese {
63//! #[derive(Debug, PartialEq, StructOfArray)]
64//! #[soa_attr(Vec, cfg_attr(test, derive(PartialEq)))]
65//! pub struct Cheese {
66//! pub smell: f64,
67//! pub color: (f64, f64, f64),
68//! pub with_mushrooms: bool,
69//! pub name: String,
70//! }
71//! # }
72//! ```
73//!
74//! Mappings for first argument of ``soa_attr`` to the generated struct for ``Cheese``:
75//! * `Vec` => `CheeseVec`
76//! * `Slice` => `CheeseSlice`
77//! * `SliceMut` => `CheeseSliceMut`
78//! * `Ref` => `CheeseRef`
79//! * `RefMut` => `CheeseRefMut`
80//! * `Ptr` => `CheesePtr`
81//! * `PtrMut` => `CheesePtrMut`
82//!
83//! # Usage and API
84//!
85//! All the generated code have some generated documentation with it, so you
86//! should be able to use `cargo doc` on your crate and see the documentation
87//! for all the generated structs and functions.
88//!
89//! Most of the time, you should be able to replace `Vec<Cheese>` by
90//! `CheeseVec`, with exception of code using direct indexing in the vector and
91//! a few other caveats listed below.
92//!
93//! ## Caveats and limitations
94//!
95//! `Vec<T>` functionalities rely a lot on references and automatic *deref*
96//! feature, for getting function from `[T]` and indexing. But the SoA vector
97//! (let's call it `CheeseVec`, generated from the `Cheese` struct) generated by
98//! this crate can not implement `Deref<Target=CheeseSlice>`, because `Deref` is
99//! required to return a reference, and `CheeseSlice` is not a reference. The
100//! same applies to `Index` and `IndexMut` trait, that can not return
101//! `CheeseRef/CheeseRefMut`.
102//!
103//! This means that the we can not index into a `CheeseVec`, and that a few
104//! functions are duplicated, or require a call to `as_ref()/as_mut()` to change
105//! the type used.
106//!
107//! # Iteration
108//!
109//! It is possible to iterate over the values in a `CheeseVec`
110//!
111//! ```no_run
112//! # #[macro_use] extern crate soa_derive;
113//! # mod cheese {
114//! # #[derive(Debug, PartialEq, StructOfArray)]
115//! # pub struct Cheese {
116//! # pub smell: f64,
117//! # pub color: (f64, f64, f64),
118//! # pub with_mushrooms: bool,
119//! # pub name: String,
120//! # }
121//! # impl Cheese { fn new(name: &str) -> Cheese { unimplemented!() } }
122//! # fn main() {
123//! let mut vec = CheeseVec::new();
124//! vec.push(Cheese::new("stilton"));
125//! vec.push(Cheese::new("brie"));
126//!
127//! for cheese in vec.iter() {
128//! // when iterating over a CheeseVec, we load all members from memory
129//! // in a CheeseRef
130//! let typeof_cheese: CheeseRef = cheese;
131//! println!("this is {}, with a smell power of {}", cheese.name, cheese.smell);
132//! }
133//! # }
134//! # }
135//! ```
136//!
137//! One of the main advantage of the SoA layout is to be able to only load some
138//! fields from memory when iterating over the vector. In order to do so, one
139//! can manually pick the needed fields:
140//!
141//! ```no_run
142//! # #[macro_use] extern crate soa_derive;
143//! # mod cheese {
144//! # #[derive(Debug, PartialEq, StructOfArray)]
145//! # pub struct Cheese {
146//! # pub smell: f64,
147//! # pub color: (f64, f64, f64),
148//! # pub with_mushrooms: bool,
149//! # pub name: String,
150//! # }
151//! # impl Cheese { fn new(name: &str) -> Cheese { unimplemented!() } }
152//! # fn main() {
153//! # let mut vec = CheeseVec::new();
154//! # vec.push(Cheese::new("stilton"));
155//! # vec.push(Cheese::new("brie"));
156//! for name in &vec.name {
157//! // We get referenes to the names
158//! let typeof_name: &String = name;
159//! println!("got cheese {}", name);
160//! }
161//! # }
162//! # }
163//! ```
164//!
165//! In order to iterate over multiple fields at the same time, one can use the
166//! [soa_zip!](macro.soa_zip.html) macro.
167//!
168//! ```no_run
169//! # #[macro_use] extern crate soa_derive;
170//! # mod cheese {
171//! # #[derive(Debug, PartialEq, StructOfArray)]
172//! # pub struct Cheese {
173//! # pub smell: f64,
174//! # pub color: (f64, f64, f64),
175//! # pub with_mushrooms: bool,
176//! # pub name: String,
177//! # }
178//! # impl Cheese { fn new(name: &str) -> Cheese { unimplemented!() } }
179//! # fn main() {
180//! # let mut vec = CheeseVec::new();
181//! # vec.push(Cheese::new("stilton"));
182//! # vec.push(Cheese::new("brie"));
183//! for (name, smell, color) in soa_zip!(&mut vec, [name, mut smell, color]) {
184//! println!("this is {}, with color {:#?}", name, color);
185//! // smell is a mutable reference
186//! *smell += 1.0;
187//! }
188//! # }
189//! # }
190//! ```
191//!
192//! ## Nested Struct of Arrays
193//!
194//! In order to nest a struct of arrays inside another struct of arrays, one can use the `#[nested_soa]` attribute.
195//!
196//! For example, the following code
197//!
198//! ```
199//! # mod cheese {
200//! # use soa_derive::StructOfArray;
201//! #[derive(StructOfArray)]
202//! pub struct Point {
203//! x: f32,
204//! y: f32,
205//! }
206//! #[derive(StructOfArray)]
207//! pub struct Particle {
208//! #[nested_soa]
209//! point: Point,
210//! mass: f32,
211//! }
212//! # }
213//! ```
214//!
215//! will generate structs that looks like this:
216//!
217//! ```
218//! pub struct PointVec {
219//! x: Vec<f32>,
220//! y: Vec<f32>,
221//! }
222//! pub struct ParticleVec {
223//! point: PointVec, // rather than Vec<Point>
224//! mass: Vec<f32>
225//! }
226//! ```
227//!
228//! All helper structs will be also nested, for example `PointSlice` will be nested in `ParticleSlice`.
229//!
230//! # Use in a generic context
231//!
232//! `StructOfArray` does not provide a set of common operations by default. Thus if you wanted to use a `StructOfArray`
233//! type in a generic context, there is no way to guarantee to the type system that any methods are available.
234//!
235//! This will also generate implementations of [`SoAVec`], [`SoASlice`], and [`SoASliceMut`] for the respective
236//! `Vec`, `Slice` and `SliceMut` types. These rely on GATs, and so require Rust 1.65 or newer.
237//!
238//! ```ignore
239//! # mod cheese {
240//! # use soa_derive::{StructOfArray, prelude::*};
241//! #[derive(StructOfArray)]
242//! pub struct Point {
243//! x: f32,
244//! y: f32,
245//! }
246//!
247//! fn get_num_items<T: StructOfArray, V: SoAVec<T>>(values: &V) -> usize {
248//! values.len()
249//! }
250//! # }
251//! ```
252
253// The proc macro is implemented in soa_derive_internal, and re-exported by this
254// crate. This is because a single crate can not define both a proc macro and a
255// macro_rules macro.
256pub use soa_derive_internal::StructOfArray;
257
258// External dependency necessary for implementing the sorting methods.
259// It is basically used by the macro-generated code.
260#[doc(hidden)]
261pub use permutation::permutation::*;
262
263/// Any struct derived by StructOfArray will auto impl this trait You can use
264/// `<Cheese as StructOfArray>::Type` instead of explicit named type
265/// `CheeseVec`; This will helpful in generics programing that generate struct
266/// can be expressed as `<T as StructOfArray>::Type`
267pub trait StructOfArray {
268 type Type;
269}
270
271/// Any struct derived by StructOfArray will auto impl this trait.
272///
273/// Useful for generic programming and implementation of attribute `nested_soa`.
274///
275/// `CheeseVec::iter(&'a self)` returns an iterator which has a type `<Cheese as SoAIter<'a>>::Iter`
276///
277/// `CheeseVec::iter_mut(&mut 'a self)` returns an iterator which has a type `<Cheese as SoAIter<'a>>::IterMut`
278pub trait SoAIter<'a> {
279 type Ref;
280 type RefMut;
281 type Iter: 'a + Iterator<Item=Self::Ref>;
282 type IterMut: 'a + Iterator<Item=Self::RefMut>;
283}
284
285mod private_soa_indexes {
286 // From [`std::slice::SliceIndex`](https://doc.rust-lang.org/std/slice/trait.SliceIndex.html) code.
287 // Limits the types that may implement the SoA index traits.
288 // It's also helpful to have the exaustive list of all accepted types.
289
290 use ::std::ops;
291
292 pub trait Sealed {}
293
294 impl Sealed for usize {} // [a]
295 impl Sealed for ops::Range<usize> {} // [a..b]
296 impl Sealed for ops::RangeTo<usize> {} // [..b]
297 impl Sealed for ops::RangeFrom<usize> {} // [a..]
298 impl Sealed for ops::RangeFull {} // [..]
299 impl Sealed for ops::RangeInclusive<usize> {} // [a..=b]
300 impl Sealed for ops::RangeToInclusive<usize> {} // [..=b]
301}
302
303/// Helper trait used for indexing operations.
304/// Inspired by [`std::slice::SliceIndex`](https://doc.rust-lang.org/std/slice/trait.SliceIndex.html).
305pub trait SoAIndex<T>: private_soa_indexes::Sealed {
306 /// The output for the non-mutable functions
307 type RefOutput;
308
309 /// Returns the reference output in this location if in bounds, `None`
310 /// otherwise.
311 fn get(self, soa: T) -> Option<Self::RefOutput>;
312 /// Returns the reference output in this location without performing any
313 /// bounds check.
314 ///
315 /// # Safety
316 /// The index must be in bounds.
317 unsafe fn get_unchecked(self, soa: T) -> Self::RefOutput;
318 /// Returns the reference output in this location. Panics if it is not in
319 /// bounds.
320 fn index(self, soa: T) -> Self::RefOutput;
321}
322
323/// Helper trait used for indexing operations returning mutable references.
324/// Inspired by [`std::slice::SliceIndex`](https://doc.rust-lang.org/std/slice/trait.SliceIndex.html).
325pub trait SoAIndexMut<T>: private_soa_indexes::Sealed {
326 /// The output for the mutable functions
327 type MutOutput;
328
329 /// Returns the mutable reference output in this location if in bounds,
330 /// `None` otherwise.
331 fn get_mut(self, soa: T) -> Option<Self::MutOutput>;
332 /// Returns the mutable reference output in this location without performing
333 /// any bounds check.
334 ///
335 /// # Safety
336 /// The index must be in bounds.
337 unsafe fn get_unchecked_mut(self, soa: T) -> Self::MutOutput;
338 /// Returns the mutable reference output in this location. Panics if it is
339 /// not in bounds.
340 fn index_mut(self, soa: T) -> Self::MutOutput;
341}
342
343/// Create an iterator over multiple fields in a Struct of array style vector.
344///
345/// This macro takes two main arguments: the array/slice container, and a list
346/// of fields to use, inside square brackets. The iterator will give references
347/// to the fields, which can be mutable references if the field name is prefixed
348/// with `mut`.
349///
350/// ```
351/// # #[macro_use] extern crate soa_derive;
352/// # mod cheese {
353/// #[derive(StructOfArray)]
354/// struct Cheese {
355/// size: f64,
356/// mass: f64,
357/// smell: f64,
358/// name: String,
359/// }
360///
361/// # fn main() {
362/// let mut vec = CheeseVec::new();
363/// // fill the vector
364///
365/// // Iterate over immutable references
366/// for (mass, size, name) in soa_zip!(&vec, [mass, size, name]) {
367/// println!("got {} kg and {} cm of {}", mass, size, name);
368/// }
369///
370/// // Iterate over mutable references
371/// for (mass, name) in soa_zip!(&mut vec, [mut mass, name]) {
372/// println!("got {} kg of {}, eating 1 kg", mass, name);
373/// *mass -= 1.0;
374/// }
375/// # }
376/// # }
377/// ```
378///
379/// The iterator can also work with external iterators. In this case, the
380/// iterator will yields elements until any of the fields or one external
381/// iterator returns None.
382///
383/// ```
384/// # #[macro_use] extern crate soa_derive;
385/// # mod cheese {
386/// # #[derive(StructOfArray)]
387/// # struct Cheese {
388/// # size: f64,
389/// # mass: f64,
390/// # smell: f64,
391/// # name: String,
392/// # }
393/// # #[derive(Debug)] struct Cellar;
394/// # fn main() {
395/// let mut vec = CheeseVec::new();
396/// let mut cellars = Vec::<Cellar>::new();
397///
398/// for (name, mass, cellar) in soa_zip!(&vec, [name, mass], &cellars) {
399/// println!("we have {} kg of {} in {:#?}", mass, name, cellar);
400/// }
401/// # }
402/// # }
403/// ```
404#[macro_export]
405macro_rules! soa_zip {
406 ($self: expr, [$($fields: tt)*] $(, $external: expr)* $(,)*) => {{
407 let this = $self;
408 $crate::soa_zip_impl!(@munch this, {$($fields)*} -> [] $($external ,)*)
409 }};
410}
411
412
413/// This trait is automatically implemented by the relevant generated by [`StructOfArray`].
414///
415/// Links a [`StructOfArray`] type to its raw pointer types, which is useful for generic
416/// programming.
417pub trait SoAPointers {
418 /// The immutable pointer type for an SoA type
419 type Ptr;
420 /// The mutable pointer type for an SoA type
421 type MutPtr;
422}
423
424
425mod generics {
426 use super::*;
427
428 /**
429 The interface for the `Slice` immutable slice struct-of-arrays type.
430 */
431 pub trait SoASlice<T: StructOfArray> {
432 /// The type that elements will be proxied with as
433 type Ref<'t> where Self: 't;
434
435 /// The type representing immutable slices of elements
436 type Slice<'t>: SoASlice<T> + IntoSoAIter<'t, T, Ref<'t> = Self::Ref<'t>> where Self: 't;
437
438 /// The type used for iteration over [`Self::Ref`]
439 type Iter<'t>: Iterator<Item=Self::Ref<'t>> where Self: 't;
440
441 /// The raw pointer type interface
442 type Ptr;
443
444 /// Returns the number of elements in the arrays
445 fn len(&self) -> usize;
446
447 /// Returns true if the arrays has a length of 0.
448 fn is_empty(&self) -> bool;
449
450 /// Create an immutable slice of the arrays
451 fn as_slice(&self) -> Self::Slice<'_>;
452
453 /// Create a slice of this vector matching the given `range`. This
454 /// is analogous to `Index<Range<usize>>`.
455 fn slice<'c, 'a: 'c>(&'c self, index: impl core::ops::RangeBounds<usize>) -> Self::Slice<'c> where Self: 'a;
456
457 /// Analogous to [`slice::get()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get)
458 fn get(&self, index: usize) -> Option<Self::Ref<'_>>;
459
460 /// Analogous to [`std::ops::Index::index()`] for `usize`
461 fn index(&self, index: usize) -> Self::Ref<'_>;
462
463 /// Create an immutable iterator
464 fn iter(&self) -> Self::Iter<'_>;
465
466 /// Analogous to [`slice::first()`](https://doc.rust-lang.org/std/primitive.slice.html#method.first)
467 fn first(&self) -> Option<Self::Ref<'_>> {
468 self.get(0)
469 }
470
471 /// Analogous to [`slice::last()`](https://doc.rust-lang.org/std/primitive.slice.html#method.last)
472 fn last(&self) -> Option<Self::Ref<'_>> {
473 self.get(self.len().saturating_sub(1))
474 }
475
476 /// Obtain a `const` pointer type for this data
477 fn as_ptr(&self) -> Self::Ptr;
478 }
479
480 /**
481 The interface for the `SliceMut` mutable slice struct-of-arrays type. A generalization of [`SoASlice`]
482 whose methods can modify elements of the arrays
483 */
484 pub trait SoASliceMut<T: StructOfArray> {
485 /// The type that elements will be proxied with as
486 type Ref<'t> where Self: 't;
487
488 /// The type representing immutable slices of elements
489 type Slice<'t>: SoASlice<T> + IntoSoAIter<'t, T, Ref<'t> = Self::Ref<'t>> where Self: 't;
490
491 /// The type used for iteration over [`Self::Ref`]
492 type Iter<'t>: Iterator<Item=Self::Ref<'t>> where Self: 't;
493
494 /// The const pointer type interface
495 type Ptr;
496
497 /// The type that elements will be proxied with as when mutable
498 type RefMut<'t> where Self: 't;
499
500 /// The type representing mutable slices of elements
501 type SliceMut<'t>: SoASliceMut<T> where Self: 't;
502
503 /// The type used for iteration over [`Self::RefMut`]
504 type IterMut<'t>: Iterator<Item=Self::RefMut<'t>> where Self: 't;
505
506 /// The mut pointer type interface
507 type PtrMut;
508
509 /// Returns the number of elements in the arrays
510 fn len(&self) -> usize;
511
512 /// Returns true if the arrays has a length of 0.
513 fn is_empty(&self) -> bool;
514
515 /// Create an immutable slice of the arrays
516 fn as_slice(&self) -> Self::Slice<'_>;
517
518 /// Create a slice of this vector matching the given `range`. This
519 /// is analogous to `Index<Range<usize>>`.
520 fn slice<'c, 'a: 'c>(&'c self, index: impl core::ops::RangeBounds<usize>) -> Self::Slice<'c> where Self: 'a;
521
522 /// Analogous to [`slice::get()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get)
523 fn get(&self, index: usize) -> Option<Self::Ref<'_>>;
524
525 /// Analogous to [`std::ops::Index::index()`] for `usize`
526 fn index(&self, index: usize) -> Self::Ref<'_>;
527
528 /// Create an immutable iterator
529 fn iter(&self) -> Self::Iter<'_>;
530
531 /// Analogous to [`slice::first()`](https://doc.rust-lang.org/std/primitive.slice.html#method.first)
532 fn first(&self) -> Option<Self::Ref<'_>> {
533 self.get(0)
534 }
535
536 /// Analogous to [`slice::last()`](https://doc.rust-lang.org/std/primitive.slice.html#method.last)
537 fn last(&self) -> Option<Self::Ref<'_>> {
538 self.get(self.len().saturating_sub(1))
539 }
540
541 /// Obtain a `const` pointer type for this data
542 fn as_ptr(&self) -> Self::Ptr;
543
544 /// Analogous to [`Vec::as_mut_slice()`]
545 fn as_mut_slice<'c: 'b, 'b>(&'c mut self) -> Self::SliceMut<'c> where Self: 'b;
546
547 /// Create a mutable slice of this vector matching the given
548 /// `range`. This is analogous to `IndexMut<Range<usize>>`.
549 fn slice_mut(&mut self, index: impl core::ops::RangeBounds<usize>) -> Self::SliceMut<'_>;
550
551 /// Analogous to [`slice::get_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_mut)
552 fn get_mut(&mut self, index: usize) -> Option<Self::RefMut<'_>>;
553
554 /// Analogous to [`std::ops::IndexMut::index_mut()`] for `usize`
555 fn index_mut(&mut self, index: usize) -> Self::RefMut<'_>;
556
557 /// Creates a mutable iterator
558 fn iter_mut(&mut self) -> Self::IterMut<'_>;
559
560 /** Re-order the arrays using the provided indices. This is provided so that generic sorting methods
561 can be implemented because closure-passing trait methods encounter difficulties with lifetimes.
562 */
563 fn apply_index(&mut self, indices: &[usize]);
564
565 /// `[slice::sort_by()`](<https://doc.rust-lang.org/std/primitive.slice.html#method.sort_by>).
566 fn sort_by<F>(&mut self, mut f: F) where F: FnMut(Self::Ref<'_>, Self::Ref<'_>) -> std::cmp::Ordering {
567 let mut permutation: Vec<usize> = (0..self.len()).collect();
568 permutation.sort_by(|j, k| f(self.index(*j), self.index(*k)));
569
570 self.apply_index(&permutation);
571 }
572
573 /// `[slice::sort_by()`](<https://doc.rust-lang.org/std/primitive.slice.html#method.sort_by_key>).
574 fn sort_by_key<F, K>(&mut self, mut f: F) where
575 F: FnMut(Self::Ref<'_>) -> K,
576 K: Ord,
577 {
578 let mut permutation: Vec<usize> = (0..self.len()).collect();
579 permutation.sort_by_key(|j| f(self.index(*j)));
580
581 self.apply_index(&permutation);
582 }
583
584 /// Analogous to [`slice::first_mut()`](<https://doc.rust-lang.org/std/primitive.slice.html#method.first_mut>).
585 fn first_mut(&mut self) -> Option<Self::RefMut<'_>> {
586 self.get_mut(0)
587 }
588
589 /// Analogous to [`slice::last_mut()`](<https://doc.rust-lang.org/std/primitive.slice.html#method.last_mut>).
590 fn last_mut(&mut self) -> Option<Self::RefMut<'_>> {
591 self.get_mut(self.len().saturating_sub(1))
592 }
593
594 /// Obtain a `mut` pointer type for this data
595 fn as_mut_ptr(&mut self) -> Self::PtrMut;
596 }
597
598 /**
599 The interface for the `Vec`-like struct-of-arrays type. A generalization of [`SoASliceMut`] whose methods can
600 also re-size the underlying arrays.
601
602 **NOTE**: This interface is incomplete and additional methods may be added as needed.
603 */
604 pub trait SoAVec<T: StructOfArray> {
605 /// The type that elements will be proxied with as
606 type Ref<'t> where Self: 't;
607
608 /// The type representing immutable slices of elements
609 type Slice<'t>: SoASlice<T> + IntoSoAIter<'t, T> where Self: 't;
610
611 /// The type used for iteration over [`Self::Ref`]
612 type Iter<'t>: Iterator<Item=Self::Ref<'t>> where Self: 't;
613
614 /// The const pointer type interface
615 type Ptr;
616
617 /// The type that elements will be proxied with as when mutable
618 type RefMut<'t> where Self: 't;
619
620 /// The type representing mutable slices of elements
621 type SliceMut<'t>: SoASliceMut<T> where Self: 't;
622
623 /// The type used for iteration over [`Self::RefMut`]
624 type IterMut<'t>: Iterator<Item=Self::RefMut<'t>> where Self: 't;
625
626 /// The mut pointer type interface
627 type PtrMut;
628
629 /// Returns the number of elements in the arrays
630 fn len(&self) -> usize;
631
632 /// Returns true if the arrays has a length of 0.
633 fn is_empty(&self) -> bool;
634
635 /// Create an immutable slice of the arrays
636 fn as_slice<'c, 'a: 'c>(&'c self) -> Self::Slice<'c> where Self: 'a;
637
638 /// Create a slice of this vector matching the given `range`. This
639 /// is analogous to `Index<Range<usize>>`.
640 fn slice<'c, 'a: 'c>(&'c self, index: impl core::ops::RangeBounds<usize>) -> Self::Slice<'c> where Self: 'a;
641
642 /// Analogous to [`slice::get()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get)
643 fn get(&self, index: usize) -> Option<Self::Ref<'_>>;
644
645 /// Analogous to [`std::ops::Index::index()`] for `usize`
646 fn index(&self, index: usize) -> Self::Ref<'_>;
647
648 /// Create an immutable iterator
649 fn iter(&self) -> Self::Iter<'_>;
650
651 /// Analogous to [`slice::first()`](https://doc.rust-lang.org/std/primitive.slice.html#method.first)
652 fn first(&self) -> Option<Self::Ref<'_>> {
653 self.get(0)
654 }
655
656 /// Analogous to [`slice::last()`](https://doc.rust-lang.org/std/primitive.slice.html#method.last)
657 fn last(&self) -> Option<Self::Ref<'_>> {
658 self.get(self.len().saturating_sub(1))
659 }
660
661 /// Obtain a `const` pointer type for this data
662 fn as_ptr(&self) -> Self::Ptr;
663
664 /// Analogous to [`Vec::as_mut_slice()`]
665 fn as_mut_slice<'c, 'a: 'c>(&'c mut self) -> Self::SliceMut<'c> where Self: 'a;
666
667 /// Create a mutable slice of this vector matching the given
668 /// `range`. This is analogous to `IndexMut<Range<usize>>`.
669 fn slice_mut(&mut self, index: impl core::ops::RangeBounds<usize>) -> Self::SliceMut<'_>;
670
671 /// Analogous to [`slice::get_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.get_mut)
672 fn get_mut(&mut self, index: usize) -> Option<Self::RefMut<'_>>;
673
674 /// Analogous to [`std::ops::IndexMut::index_mut()`] for `usize`
675 fn index_mut(&mut self, index: usize) -> Self::RefMut<'_>;
676
677 /// Creates a mutable iterator
678 fn iter_mut(&mut self) -> Self::IterMut<'_>;
679
680 /** Re-order the arrays using the provided indices. This is provided so that generic sorting methods
681 can be implemented because closure-passing trait methods encounter difficulties with lifetimes.
682 */
683 fn apply_index(&mut self, indices: &[usize]);
684
685 /// `[slice::sort_by()`](<https://doc.rust-lang.org/std/primitive.slice.html#method.sort_by>).
686 fn sort_by<F>(&mut self, mut f: F) where F: FnMut(Self::Ref<'_>, Self::Ref<'_>) -> std::cmp::Ordering {
687 let mut permutation: Vec<usize> = (0..self.len()).collect();
688 permutation.sort_by(|j, k| f(self.index(*j), self.index(*k)));
689
690 self.apply_index(&permutation);
691 }
692
693 /// `[slice::sort_by()`](<https://doc.rust-lang.org/std/primitive.slice.html#method.sort_by_key>).
694 fn sort_by_key<F, K>(&mut self, mut f: F) where
695 F: FnMut(Self::Ref<'_>) -> K,
696 K: Ord,
697 {
698 let mut permutation: Vec<usize> = (0..self.len()).collect();
699 permutation.sort_by_key(|j| f(self.index(*j)));
700
701 self.apply_index(&permutation);
702 }
703
704 /// Analogous to [`slice::first_mut()`](<https://doc.rust-lang.org/std/primitive.slice.html#method.first_mut>)
705 fn first_mut(&mut self) -> Option<Self::RefMut<'_>> {
706 self.get_mut(0)
707 }
708
709 /// Analogous to [`slice::last_mut()`](<https://doc.rust-lang.org/std/primitive.slice.html#method.last_mut>)
710 fn last_mut(&mut self) -> Option<Self::RefMut<'_>> {
711 self.get_mut(self.len().saturating_sub(1))
712 }
713
714 /// Obtain a `mut` pointer type for this data
715 fn as_mut_ptr(&mut self) -> Self::PtrMut;
716
717 /// Create a new, empty struct of arrays
718 fn new() -> Self;
719
720 /// Create a new, empty struct of arrays with the specified capacity
721 fn with_capacity(capacity: usize) -> Self;
722
723 /// Analogous to [`Vec::capacity`]
724 fn capacity(&self) -> usize;
725
726 /// Analogous to [`Vec::reserve`]
727 fn reserve(&mut self, additional: usize);
728
729 /// Analogous to [`Vec::reserve_exact`]
730 fn reserve_exact(&mut self, additional: usize);
731
732 /// Analogous to [`Vec::shrink_to_fit`]
733 fn shrink_to_fit(&mut self);
734
735 /// Analogous to [`Vec::truncate`]
736 fn truncate(&mut self, len: usize);
737
738 /// Add a singular value of `T` to the arrays. Analogous to [`Vec::push`]
739 fn push(&mut self, value: T);
740
741 /// Analogous to [`Vec::swap_remove`]
742 fn swap_remove(&mut self, index: usize) -> T;
743
744 /// Analogous to [`Vec::insert`]
745 fn insert(&mut self, index: usize, element: T);
746
747 /// Similar to [`std::mem::replace()`](https://doc.rust-lang.org/std/mem/fn.replace.html).
748 fn replace(&mut self, index: usize, element: T) -> T;
749
750 /// Analogous to [`Vec::remove`]
751 fn remove(&mut self, index: usize) -> T;
752
753 /// Analogous to [`Vec::pop`]
754 fn pop(&mut self) -> Option<T>;
755
756 /// Analogous to [`Vec::append`]
757 fn append(&mut self, other: &mut Self);
758
759 /// Analogous to [`Vec::clear`]
760 fn clear(&mut self);
761
762 /// Analogous to [`Vec::split_off`]
763 fn split_off(&mut self, at: usize) -> Self;
764 }
765
766 /// A trait to implement `Clone`-dependent behavior to convert a non-owning SoA type into an
767 /// owning [`SoAVec`].
768 pub trait ToSoAVec<T: StructOfArray> {
769 type SoAVecType: SoAVec<T>;
770
771 /// Similar to [`slice::to_vec()`](https://doc.rust-lang.org/std/primitive.slice.html#method.to_vec)
772 fn to_vec(&self) -> Self::SoAVecType;
773 }
774
775 /// A trait to implement `Clone`-dependent behavior to extend an [`SoAVec`] with data copied
776 /// from its associated `Slice` type.
777 pub trait SoAAppendVec<T: StructOfArray>: SoAVec<T> {
778
779 /// Analogous to [`Vec::extend_from_slice`]
780 fn extend_from_slice(&mut self, other: Self::Slice<'_>);
781 }
782
783 /// A trait to express the [`IntoIterator`] guarantee of [`SoASlice`] types in the type system.
784 pub trait IntoSoAIter<'a, T: StructOfArray>: SoASlice<T> + IntoIterator<Item=Self::Ref<'a>> + 'a {}
785}
786pub use generics::*;
787
788
789#[macro_export]
790#[doc(hidden)]
791macro_rules! soa_zip_impl {
792 // @flatten creates a tuple-flattening closure for .map() call
793 // Finish recursion
794 (@flatten $p:pat => $tup:expr ) => {
795 |$p| $tup
796 };
797 // Eat an element ($_iter) and add it to the current closure. Then recurse
798 (@flatten $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => {
799 $crate::soa_zip_impl!(@flatten ($p, a) => ( $($tup)*, a ) $( , $tail )*)
800 };
801
802 // The main code is emmited here: we create an iterator, zip it and then
803 // map the zipped iterator to flatten it
804 (@last , $first: expr, $($tail: expr,)*) => {
805 ::std::iter::IntoIterator::into_iter($first)
806 $(
807 .zip($tail)
808 )*
809 .map(
810 $crate::soa_zip_impl!(@flatten a => (a) $( , $tail )*)
811 )
812 };
813
814 // Eat the last `mut $field` and then emit code
815 (@munch $self: expr, {mut $field: ident} -> [$($output: tt)*] $($ext: expr ,)*) => {
816 $crate::soa_zip_impl!(@last $($output)*, $self.$field.iter_mut(), $($ext, )*)
817 };
818 // Eat the last `$field` and then emit code
819 (@munch $self: expr, {$field: ident} -> [$($output: tt)*] $($ext: expr ,)*) => {
820 $crate::soa_zip_impl!(@last $($output)*, $self.$field.iter(), $($ext, )*)
821 };
822
823 // Eat the next `mut $field` and then recurse
824 (@munch $self: expr, {mut $field: ident, $($tail: tt)*} -> [$($output: tt)*] $($ext: expr ,)*) => {
825 $crate::soa_zip_impl!(@munch $self, {$($tail)*} -> [$($output)*, $self.$field.iter_mut()] $($ext, )*)
826 };
827 // Eat the next `$field` and then recurse
828 (@munch $self: expr, {$field: ident, $($tail: tt)*} -> [$($output: tt)*] $($ext: expr ,)*) => {
829 $crate::soa_zip_impl!(@munch $self, {$($tail)*} -> [$($output)*, $self.$field.iter()] $($ext, )*)
830 };
831}