specs/join/
mod.rs

1//! Joining of components for iteration over entities with specific components.
2
3use hibitset::{BitIter, BitSetLike};
4use shred::{Fetch, FetchMut, Read, ReadExpect, Resource, Write, WriteExpect};
5use std::ops::{Deref, DerefMut};
6
7use crate::world::Index;
8
9mod bit_and;
10mod lend_join;
11mod maybe;
12#[cfg(feature = "parallel")]
13mod par_join;
14
15pub use bit_and::BitAnd;
16#[nougat::gat(Type)]
17pub use lend_join::LendJoin;
18pub use lend_join::{JoinLendIter, LendJoinType, RepeatableLendGet};
19pub use maybe::MaybeJoin;
20#[cfg(feature = "parallel")]
21pub use par_join::{JoinParIter, ParJoin};
22
23/// The purpose of the `Join` trait is to provide a way
24/// to access multiple storages at the same time with
25/// the merged bit set.
26///
27/// Joining component storages means that you'll only get values where
28/// for a given entity every storage has an associated component.
29///
30/// ## Example
31///
32/// ```
33/// # use specs::prelude::*;
34/// # use specs::world::EntitiesRes;
35/// # #[derive(Debug, PartialEq)]
36/// # struct Pos; impl Component for Pos { type Storage = VecStorage<Self>; }
37/// # #[derive(Debug, PartialEq)]
38/// # struct Vel; impl Component for Vel { type Storage = VecStorage<Self>; }
39/// let mut world = World::new();
40///
41/// world.register::<Pos>();
42/// world.register::<Vel>();
43///
44/// {
45///     let pos = world.read_storage::<Pos>();
46///     let vel = world.read_storage::<Vel>();
47///
48///     // There are no entities yet, so no pair will be returned.
49///     let joined: Vec<_> = (&pos, &vel).join().collect();
50///     assert_eq!(joined, vec![]);
51/// }
52///
53/// world.create_entity().with(Pos).build();
54///
55/// {
56///     let pos = world.read_storage::<Pos>();
57///     let vel = world.read_storage::<Vel>();
58///
59///     // Although there is an entity, it only has `Pos`.
60///     let joined: Vec<_> = (&pos, &vel).join().collect();
61///     assert_eq!(joined, vec![]);
62/// }
63///
64/// let ent = world.create_entity().with(Pos).with(Vel).build();
65///
66/// {
67///     let pos = world.read_storage::<Pos>();
68///     let vel = world.read_storage::<Vel>();
69///
70///     // Now there is one entity that has both a `Vel` and a `Pos`.
71///     let joined: Vec<_> = (&pos, &vel).join().collect();
72///     assert_eq!(joined, vec![(&Pos, &Vel)]);
73///
74///     // If we want to get the entity the components are associated to,
75///     // we need to join over `Entities`:
76///
77///     let entities = world.read_resource::<EntitiesRes>();
78///     // note: `EntitiesRes` is the fetched resource; we get back
79///     // `Read<EntitiesRes>`.
80///     // `Read<EntitiesRes>` can also be referred to by `Entities` which
81///     // is a shorthand type definition to the former type.
82///
83///     let joined: Vec<_> = (&entities, &pos, &vel).join().collect();
84///     assert_eq!(joined, vec![(ent, &Pos, &Vel)]);
85/// }
86/// ```
87///
88/// ## Iterating over a single storage
89///
90/// `Join` can also be used to iterate over a single
91/// storage, just by writing `(&storage).join()`.
92///
93/// # Safety
94///
95/// The `Self::Mask` value returned with the `Self::Value` must correspond such
96/// that it is safe to retrieve items from `Self::Value` whose presence is
97/// indicated in the mask. As part of this, `BitSetLike::iter` must not produce
98/// an iterator that repeats an `Index` value.
99pub unsafe trait Join {
100    /// Type of joined components.
101    type Type;
102    /// Type of joined storages.
103    type Value;
104    /// Type of joined bit mask.
105    type Mask: BitSetLike;
106
107    /// Create a joined iterator over the contents.
108    fn join(self) -> JoinIter<Self>
109    where
110        Self: Sized,
111    {
112        JoinIter::new(self)
113    }
114
115    /// Open this join by returning the mask and the storages.
116    ///
117    /// # Safety
118    ///
119    /// This is unsafe because implementations of this trait can permit the
120    /// `Value` to be mutated independently of the `Mask`. If the `Mask` does
121    /// not correctly report the status of the `Value` then illegal memory
122    /// access can occur.
123    unsafe fn open(self) -> (Self::Mask, Self::Value);
124
125    /// Get a joined component value by a given index.
126    ///
127    ///
128    /// # Safety
129    ///
130    /// * A call to `get` must be preceded by a check if `id` is part of
131    ///   `Self::Mask`.
132    /// * Multiple calls with the same `id` are not allowed, for a particular
133    ///   instance of the values from [`open`](Join::open).
134    unsafe fn get(value: &mut Self::Value, id: Index) -> Self::Type;
135
136    /// If this `Join` typically returns all indices in the mask, then iterating
137    /// over only it or combined with other joins that are also dangerous will
138    /// cause the `JoinIter` to go through all indices which is usually not what
139    /// is wanted and will kill performance.
140    #[inline]
141    fn is_unconstrained() -> bool {
142        false
143    }
144}
145
146/// `JoinIter` is an `Iterator` over a group of storages.
147#[must_use]
148pub struct JoinIter<J: Join> {
149    keys: BitIter<J::Mask>,
150    values: J::Value,
151}
152
153impl<J: Join> JoinIter<J> {
154    /// Create a new join iterator.
155    pub fn new(j: J) -> Self {
156        if <J as Join>::is_unconstrained() {
157            log::warn!(
158                "`Join` possibly iterating through all indices, \
159                you might've made a join with all `MaybeJoin`s, \
160                which is unbounded in length."
161            );
162        }
163
164        // SAFETY: We do not swap out the mask or the values, nor do we allow it
165        // by exposing them.
166        let (keys, values) = unsafe { j.open() };
167        JoinIter {
168            keys: keys.iter(),
169            values,
170        }
171    }
172}
173
174impl<J: Join> std::iter::Iterator for JoinIter<J> {
175    type Item = J::Type;
176
177    fn next(&mut self) -> Option<J::Type> {
178        // SAFETY: Since `idx` is yielded from `keys` (the mask), it is
179        // necessarily a part of it. `Join` requires that the iterator doesn't
180        // repeat indices and we advance the iterator for each `get` call.
181        self.keys
182            .next()
183            .map(|idx| unsafe { J::get(&mut self.values, idx) })
184    }
185}
186
187// Implementations of `LendJoin`, `Join`, and `ParJoin` for tuples, `Fetch`,
188// `Read`, `ReadExpect`, `FetchMut`, `Write`, and `WriteExpect`.
189
190macro_rules! define_open {
191    // use variables to indicate the arity of the tuple
192    ($($from:ident),*) => {
193        // SAFETY: The returned mask in `open` is the intersection of the masks
194        // from each type in this tuple. So if an `id` is present in the
195        // combined mask, it will be safe to retrieve the corresponding items.
196        // Iterating the mask does not repeat indices.
197        #[nougat::gat]
198        unsafe impl<$($from,)*> LendJoin for ($($from),*,)
199            where $($from: LendJoin),*,
200                  ($(<$from as LendJoin>::Mask,)*): BitAnd,
201        {
202            type Type<'next> = ($(<$from as LendJoin>::Type<'next>),*,);
203            type Value = ($($from::Value),*,);
204            type Mask = <($($from::Mask,)*) as BitAnd>::Value;
205
206            #[allow(non_snake_case)]
207            unsafe fn open(self) -> (Self::Mask, Self::Value) {
208                let ($($from,)*) = self;
209                // SAFETY: While we do expose the mask and the values and
210                // therefore would allow swapping them, this method is `unsafe`
211                // and relies on the same invariants.
212                let ($($from,)*) = unsafe { ($($from.open(),)*) };
213                (
214                    ($($from.0),*,).and(),
215                    ($($from.1),*,)
216                )
217            }
218
219            #[allow(non_snake_case)]
220            unsafe fn get<'next>(v: &'next mut Self::Value, i: Index) -> Self::Type<'next>
221
222            {
223                let &mut ($(ref mut $from,)*) = v;
224                // SAFETY: `get` is safe to call as the caller must have checked
225                // the mask, which only has a key that exists in all of the
226                // storages. Requirement to not call with the same ID more than
227                // once (unless `RepeatableLendGet` is implemented) is passed to
228                // the caller.
229                unsafe { ($($from::get($from, i),)*) }
230            }
231
232            #[inline]
233            fn is_unconstrained() -> bool {
234                let mut unconstrained = true;
235                $( unconstrained = unconstrained && $from::is_unconstrained(); )*
236                unconstrained
237            }
238        }
239
240        // SAFETY: Tuple impls of `LendJoin` simply defer to the individual
241        // storages. Thus, if all of them implement this, it is safe to call
242        // `LendJoin::get` multiple times with the same ID.
243        unsafe impl<$($from,)*> RepeatableLendGet for ($($from),*,)
244            where $($from: RepeatableLendGet),*,
245                  ($(<$from as LendJoin>::Mask,)*): BitAnd, {}
246
247        // SAFETY: The returned mask in `open` is the intersection of the masks
248        // from each type in this tuple. So if an `id` is present in the
249        // combined mask, it will be safe to retrieve the corresponding items.
250        // Iterating the mask does not repeat indices.
251        unsafe impl<$($from,)*> Join for ($($from),*,)
252            where $($from: Join),*,
253                  ($(<$from as Join>::Mask,)*): BitAnd,
254        {
255            type Type = ($($from::Type),*,);
256            type Value = ($($from::Value),*,);
257            type Mask = <($($from::Mask,)*) as BitAnd>::Value;
258
259            #[allow(non_snake_case)]
260            unsafe fn open(self) -> (Self::Mask, Self::Value) {
261                let ($($from,)*) = self;
262                // SAFETY: While we do expose the mask and the values and
263                // therefore would allow swapping them, this method is `unsafe`
264                // and relies on the same invariants.
265                let ($($from,)*) = unsafe { ($($from.open(),)*) };
266                (
267                    ($($from.0),*,).and(),
268                    ($($from.1),*,)
269                )
270            }
271
272            #[allow(non_snake_case)]
273            unsafe fn get(v: &mut Self::Value, i: Index) -> Self::Type {
274                let &mut ($(ref mut $from,)*) = v;
275                // SAFETY: `get` is safe to call as the caller must have checked
276                // the mask, which only has a key that exists in all of the
277                // storages. Requirement to not use the same ID multiple times
278                // is also passed to the caller.
279                unsafe { ($($from::get($from, i),)*) }
280            }
281
282            #[inline]
283            fn is_unconstrained() -> bool {
284                let mut unconstrained = true;
285                $( unconstrained = unconstrained && $from::is_unconstrained(); )*
286                unconstrained
287            }
288        }
289
290        // SAFETY: This is safe to implement since all components implement
291        // `ParJoin`. If the access of every individual `get` is callable from
292        // multiple threads, then this `get` method will be as well.
293        //
294        // The returned mask in `open` is the intersection of the masks
295        // from each type in this tuple. So if an `id` is present in the
296        // combined mask, it will be safe to retrieve the corresponding items.
297        // Iterating the mask does not repeat indices.
298        #[cfg(feature = "parallel")]
299        unsafe impl<$($from,)*> ParJoin for ($($from),*,)
300            where $($from: ParJoin),*,
301                  ($(<$from as ParJoin>::Mask,)*): BitAnd,
302        {
303            type Type = ($($from::Type),*,);
304            type Value = ($($from::Value),*,);
305            type Mask = <($($from::Mask,)*) as BitAnd>::Value;
306
307            #[allow(non_snake_case)]
308            unsafe fn open(self) -> (Self::Mask, Self::Value) {
309                let ($($from,)*) = self;
310                // SAFETY: While we do expose the mask and the values and
311                // therefore would allow swapping them, this method is `unsafe`
312                // and relies on the same invariants.
313                let ($($from,)*) = unsafe { ($($from.open(),)*) };
314                (
315                    ($($from.0),*,).and(),
316                    ($($from.1),*,)
317                )
318            }
319
320            #[allow(non_snake_case)]
321            unsafe fn get(v: &Self::Value, i: Index) -> Self::Type {
322                let &($(ref $from,)*) = v;
323                // SAFETY: `get` is safe to call as the caller must have checked
324                // the mask, which only has a key that exists in all of the
325                // storages. Requirement for the return value to no longer be
326                // alive before subsequent calls with the same `id` is passed to
327                // the caller.
328                unsafe { ($($from::get($from, i),)*) }
329            }
330
331            #[inline]
332            fn is_unconstrained() -> bool {
333                let mut unconstrained = true;
334                $( unconstrained = unconstrained && $from::is_unconstrained(); )*
335                unconstrained
336            }
337        }
338    }
339}
340
341define_open! {A}
342define_open! {A, B}
343define_open! {A, B, C}
344define_open! {A, B, C, D}
345define_open! {A, B, C, D, E}
346define_open! {A, B, C, D, E, F}
347define_open! {A, B, C, D, E, F, G}
348define_open! {A, B, C, D, E, F, G, H}
349define_open! {A, B, C, D, E, F, G, H, I}
350define_open! {A, B, C, D, E, F, G, H, I, J}
351define_open! {A, B, C, D, E, F, G, H, I, J, K}
352define_open! {A, B, C, D, E, F, G, H, I, J, K, L}
353define_open! {A, B, C, D, E, F, G, H, I, J, K, L, M}
354define_open! {A, B, C, D, E, F, G, H, I, J, K, L, M, N}
355define_open! {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O}
356define_open! {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P}
357define_open!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
358define_open!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
359
360/// `Fetch`/`Read`/`Write`/etc. all implement `Deref`/`DerefMut` but Rust does
361/// not implicitly dereference the wrapper type when we are joining which
362/// creates annoying scenarios like `&*entities` where we have to reborrow the
363/// type unnecessarily.
364///
365/// So instead, we implement `Join` on the wrapper types and forward the
366/// implementations to the underlying types so that Rust doesn't have to do
367/// implicit magic to figure out what we want to do with the type.
368macro_rules! immutable_resource_join {
369    ($($ty:ty),*) => {
370        $(
371        // SAFETY: Since `T` implements `LendJoin` it is safe to deref and defer
372        // to its implementation.
373        #[nougat::gat]
374        unsafe impl<'a, 'b, T> LendJoin for &'a $ty
375        where
376            &'a T: LendJoin,
377            T: Resource,
378        {
379            type Type<'next> = <&'a T as LendJoin>::Type<'next>;
380            type Value = <&'a T as LendJoin>::Value;
381            type Mask = <&'a T as LendJoin>::Mask;
382
383            unsafe fn open(self) -> (Self::Mask, Self::Value) {
384                // SAFETY: This only wraps `T` and, while exposing the mask and
385                // the values, requires the same invariants as the original
386                // implementation and is thus safe.
387                unsafe { self.deref().open() }
388            }
389
390            unsafe fn get<'next>(v: &'next mut Self::Value, i: Index) -> Self::Type<'next>
391
392            {
393                // SAFETY: The mask of `Self` and `T` are identical, thus a
394                // check to `Self`'s mask (which is required) is equal to a
395                // check of `T`'s mask, which makes `get` safe to call.
396                // Requirement to not call with the same ID more than once
397                // (unless `RepeatableLendGet` is implemented) is passed to the
398                // caller.
399                unsafe { <&'a T as LendJoin>::get(v, i) }
400            }
401
402            #[inline]
403            fn is_unconstrained() -> bool {
404                <&'a T as LendJoin>::is_unconstrained()
405            }
406        }
407
408        // SAFETY: <&'a $ty as LendJoin>::get does not rely on only being called
409        // once with a particular ID as long as `&'a T` does not rely on this.
410        unsafe impl<'a, 'b, T> RepeatableLendGet for &'a $ty
411        where
412            &'a T: RepeatableLendGet,
413            T: Resource,
414        {}
415
416        // SAFETY: Since `T` implements `Join` it is safe to deref and defer to
417        // its implementation.
418        unsafe impl<'a, 'b, T> Join for &'a $ty
419        where
420            &'a T: Join,
421            T: Resource,
422        {
423            type Type = <&'a T as Join>::Type;
424            type Value = <&'a T as Join>::Value;
425            type Mask = <&'a T as Join>::Mask;
426
427            unsafe fn open(self) -> (Self::Mask, Self::Value) {
428                // SAFETY: This only wraps `T` and, while exposing the mask and
429                // the values, requires the same invariants as the original
430                // implementation and is thus safe.
431                unsafe { self.deref().open() }
432            }
433
434            unsafe fn get(v: &mut Self::Value, i: Index) -> Self::Type {
435                // SAFETY: The mask of `Self` and `T` are identical, thus a
436                // check to `Self`'s mask (which is required) is equal to a
437                // check of `T`'s mask, which makes `get` safe to call.
438                // Requirement to not use the same ID multiple times is passed
439                // to the caller.
440                unsafe { <&'a T as Join>::get(v, i) }
441            }
442
443            #[inline]
444            fn is_unconstrained() -> bool {
445                <&'a T as Join>::is_unconstrained()
446            }
447        }
448
449        // SAFETY: Since `T` implements `ParJoin` it is safe to deref and defer to
450        // its implementation. S-TODO we can rely on errors if $ty is not sync?
451        // Iterating the mask does not repeat indices.
452        #[cfg(feature = "parallel")]
453        unsafe impl<'a, 'b, T> ParJoin for &'a $ty
454        where
455            &'a T: ParJoin,
456            T: Resource,
457        {
458            type Type = <&'a T as ParJoin>::Type;
459            type Value = <&'a T as ParJoin>::Value;
460            type Mask = <&'a T as ParJoin>::Mask;
461
462            unsafe fn open(self) -> (Self::Mask, Self::Value) {
463                // SAFETY: This only wraps `T` and, while exposing the mask and
464                // the values, requires the same invariants as the original
465                // implementation and is thus safe.
466                unsafe { self.deref().open() }
467            }
468
469            unsafe fn get(v: &Self::Value, i: Index) -> Self::Type {
470                // SAFETY: The mask of `Self` and `T` are identical, thus a
471                // check to `Self`'s mask (which is required) is equal to a
472                // check of `T`'s mask, which makes `get` safe to call.
473                // Requirement for the return value to no longer be alive before
474                // subsequent calls with the same ID is passed to the caller.
475                unsafe { <&'a T as ParJoin>::get(v, i) }
476            }
477
478            #[inline]
479            fn is_unconstrained() -> bool {
480                <&'a T as ParJoin>::is_unconstrained()
481            }
482        }
483        )*
484    };
485}
486
487macro_rules! mutable_resource_join {
488    ($($ty:ty),*) => {
489        $(
490        // SAFETY: Since `T` implements `LendJoin` it is safe to deref and defer
491        // to its implementation.
492        #[nougat::gat]
493        unsafe impl<'a, 'b, T> LendJoin for &'a mut $ty
494        where
495            &'a mut T: LendJoin,
496            T: Resource,
497        {
498            type Type<'next> = <&'a mut T as LendJoin>::Type<'next>;
499            type Value = <&'a mut T as LendJoin>::Value;
500            type Mask = <&'a mut T as LendJoin>::Mask;
501
502            unsafe fn open(self) -> (Self::Mask, Self::Value) {
503                // SAFETY: This only wraps `T` and, while exposing the mask and
504                // the values, requires the same invariants as the original
505                // implementation and is thus safe.
506                unsafe { self.deref_mut().open() }
507            }
508
509            unsafe fn get<'next>(v: &'next mut Self::Value, i: Index) -> Self::Type<'next>
510
511            {
512                // SAFETY: The mask of `Self` and `T` are identical, thus a
513                // check to `Self`'s mask (which is required) is equal to a
514                // check of `T`'s mask, which makes `get_mut` safe to call.
515                // Requirement to not call with the same ID more than once
516                // (unless `RepeatableLendGet` is implemented) is passed to the
517                // caller.
518                unsafe { <&'a mut T as LendJoin>::get(v, i) }
519            }
520
521            #[inline]
522            fn is_unconstrained() -> bool {
523                <&'a mut T as LendJoin>::is_unconstrained()
524            }
525        }
526
527        // SAFETY: <&'a mut $ty as LendJoin>::get does not rely on only being
528        // called once with a particular ID as long as `&'a mut T` does not rely
529        // on this.
530        unsafe impl<'a, 'b, T> RepeatableLendGet for &'a mut $ty
531        where
532            &'a mut T: RepeatableLendGet,
533            T: Resource,
534        {}
535
536        // SAFETY: Since `T` implements `Join` it is safe to deref and defer to
537        // its implementation.
538        unsafe impl<'a, 'b, T> Join for &'a mut $ty
539        where
540            &'a mut T: Join,
541            T: Resource,
542        {
543            type Type = <&'a mut T as Join>::Type;
544            type Value = <&'a mut T as Join>::Value;
545            type Mask = <&'a mut T as Join>::Mask;
546
547            unsafe fn open(self) -> (Self::Mask, Self::Value) {
548                // SAFETY: This only wraps `T` and, while exposing the mask and
549                // the values, requires the same invariants as the original
550                // implementation and is thus safe.
551                unsafe { self.deref_mut().open() }
552            }
553
554            unsafe fn get(v: &mut Self::Value, i: Index) -> Self::Type {
555                // SAFETY: The mask of `Self` and `T` are identical, thus a
556                // check to `Self`'s mask (which is required) is equal to a
557                // check of `T`'s mask, which makes `get_mut` safe to call.
558                // Requirement to not use the same ID multiple times is passed
559                // to the caller.
560                unsafe { <&'a mut T as Join>::get(v, i) }
561            }
562
563            #[inline]
564            fn is_unconstrained() -> bool {
565                <&'a mut T as Join>::is_unconstrained()
566            }
567        }
568
569        // SAFETY: Since `T` implements `ParJoin` it is safe to deref and defer
570        // its implementation. S-TODO we can rely on errors if $ty is not sync?
571        #[cfg(feature = "parallel")]
572        unsafe impl<'a, 'b, T> ParJoin for &'a mut $ty
573        where
574            &'a mut T: ParJoin,
575            T: Resource,
576        {
577            type Type = <&'a mut T as ParJoin>::Type;
578            type Value = <&'a mut T as ParJoin>::Value;
579            type Mask = <&'a mut T as ParJoin>::Mask;
580
581            unsafe fn open(self) -> (Self::Mask, Self::Value) {
582                // SAFETY: This only wraps `T` and, while exposing the mask and
583                // the values, requires the same invariants as the original
584                // implementation and is thus safe.
585                unsafe { self.deref_mut().open() }
586            }
587
588            unsafe fn get(v: &Self::Value, i: Index) -> Self::Type {
589                // SAFETY: The mask of `Self` and `T` are identical, thus a
590                // check to `Self`'s mask (which is required) is equal to a
591                // check of `T`'s mask, which makes `get_mut` safe to call.
592                // Requirement for the return value to no longer be alive before
593                // subsequent calls with the same ID is passed to the caller.
594                unsafe { <&'a mut T as ParJoin>::get(v, i) }
595            }
596
597            #[inline]
598            fn is_unconstrained() -> bool {
599                <&'a mut T as ParJoin>::is_unconstrained()
600            }
601        }
602        )*
603    };
604}
605
606immutable_resource_join!(Fetch<'b, T>, Read<'b, T>, ReadExpect<'b, T>);
607mutable_resource_join!(FetchMut<'b, T>, Write<'b, T>, WriteExpect<'b, T>);