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
use hibitset::{BitSet, BitSetLike};
use specs::{Entity, Join};

pub trait GuidedJoin<'a, G, I>: Join
where
    G: 'a + IntoIterator<Item = &'a Entity, IntoIter = I>,
    I: 'a + Iterator<Item = &'a Entity>,
    <Self as Join>::Type: 'a,
{
    #[inline]
    fn guided_join(self, guide: G) -> GuidedJoinIter<'a, Self, I>
    where
        Self: Sized,
    {
        GuidedJoinIter::new(self, guide.into_iter())
    }
}

impl<'a, J, G, I> GuidedJoin<'a, G, I> for J
where
    G: 'a + IntoIterator<Item = &'a Entity, IntoIter = I>,
    I: 'a + Iterator<Item = &'a Entity>,
    J: 'a + Join,
{}

pub struct GuidedJoinIter<'a, J, I>
where
    I: 'a + Iterator<Item = &'a Entity>,
    J: 'a + Join,
{
    bitset: BitSet,
    guide: I,
    values: J::Value,
}

impl<'a, J, I> GuidedJoinIter<'a, J, I>
where
    I: 'a + Iterator<Item = &'a Entity>,
    J: 'a + Join,
{
    #[inline]
    fn new(join: J, guide: I) -> Self
    where
        Self: Sized,
    {
        let (keys, values) = unsafe { join.open() };

        let mut bitset = BitSet::new();

        for idx in keys.iter() {
            bitset.add(idx);
        }

        GuidedJoinIter {
            bitset: bitset,
            guide: guide,
            values: values,
        }
    }
}

impl<'a, J, I> Iterator for GuidedJoinIter<'a, J, I>
where
    I: 'a + Iterator<Item = &'a Entity>,
    J: 'a + Join,
{
    type Item = J::Type;

    #[inline]
    fn next(&mut self) -> Option<J::Type> {
        while let Some(entity) = self.guide.next() {
            let index = entity.id();

            if self.bitset.contains(index) {
                return Some(unsafe { J::get(&mut self.values, index) });
            }
        }
        None
    }
}