1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! Implementations and structures related to bitsets.
//!
//! Normally used for `Join`s and filtering entities.

#![cfg_attr(rustfmt, rustfmt::skip)]

use hibitset::{AtomicBitSet, BitSet, BitSetAnd, BitSetLike, BitSetNot, BitSetOr, BitSetXor};

#[nougat::gat(Type)]
use crate::join::LendJoin;
#[cfg(feature = "parallel")]
use crate::join::ParJoin;
use crate::join::{Join, RepeatableLendGet};
use crate::world::Index;

macro_rules! define_bit_join {
    ( impl < ( $( $lifetime:tt )* ) ( $( $arg:ident ),* ) > for $bitset:ty ) => {
        // SAFETY: `get` just returns the provided `id` (`Self::Value` is `()`
        // and corresponds with any mask instance).
        #[nougat::gat]
        unsafe impl<$( $lifetime, )* $( $arg ),*> LendJoin for $bitset
            where $( $arg: BitSetLike ),*
        {
            type Type<'next> = Index;
            type Value = ();
            type Mask = $bitset;

            unsafe fn open(self) -> (Self::Mask, Self::Value) {
                (self, ())
            }

            unsafe fn get<'next>(_: &'next mut Self::Value, id: Index) -> Self::Type<'next>

            {
                id
            }
        }

        // SAFETY: <$biset as LendJoin>::get does not rely on only being called
        // once with a particular ID
        unsafe impl<$( $lifetime, )* $( $arg ),*> RepeatableLendGet for $bitset
            where $( $arg: BitSetLike ),* {}

        // SAFETY: `get` just returns the provided `id` (`Self::Value` is `()`
        // and corresponds with any mask instance).
        unsafe impl<$( $lifetime, )* $( $arg ),*> Join for $bitset
            where $( $arg: BitSetLike ),*
        {
            type Type = Index;
            type Value = ();
            type Mask = $bitset;

            unsafe fn open(self) -> (Self::Mask, Self::Value) {
                (self, ())
            }

            unsafe fn get(_: &mut Self::Value, id: Index) -> Self::Type {
                id
            }
        }

        // SAFETY: `get` is safe to call concurrently and just returns the
        // provided `id` (`Self::Value` is `()` and corresponds with any mask
        // instance).
        #[cfg(feature = "parallel")]
        unsafe impl<$( $lifetime, )* $( $arg ),*> ParJoin for $bitset
            where $( $arg: BitSetLike ),*
        {
            type Type = Index;
            type Value = ();
            type Mask = $bitset;

            unsafe fn open(self) -> (Self::Mask, Self::Value) {
                (self, ())
            }

            unsafe fn get(_: &Self::Value, id: Index) -> Self::Type {
                id
            }
        }
    }
}

define_bit_join!(impl<()()> for BitSet);
define_bit_join!(impl<('a)()> for &'a BitSet);
define_bit_join!(impl<()()> for AtomicBitSet);
define_bit_join!(impl<('a)()> for &'a AtomicBitSet);
define_bit_join!(impl<()(A)> for BitSetNot<A>);
define_bit_join!(impl<('a)(A)> for &'a BitSetNot<A>);
define_bit_join!(impl<()(A, B)> for BitSetAnd<A, B>);
define_bit_join!(impl<('a)(A, B)> for &'a BitSetAnd<A, B>);
define_bit_join!(impl<()(A, B)> for BitSetOr<A, B>);
define_bit_join!(impl<('a)(A, B)> for &'a BitSetOr<A, B>);
define_bit_join!(impl<()(A, B)> for BitSetXor<A, B>);
define_bit_join!(impl<('a)()> for &'a dyn BitSetLike);