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}