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
96
97
98
99
#[macro_use]
mod typeset;


mod component;

#[macro_export]
macro_rules! world {
    ( $i:ident { $($t:ty),+ $(,)? } ) => {
        use crate::component::{EntityID, ComponentContainer};

        typeset!{ Components { $( ComponentContainer<$t> ),+ } }
        type $i = (EntityID, Components);
        pub trait PushComponent<C> {
            fn push_component(&mut self, component: C);
        }
        $(
            impl PushComponent<$t> for $i {
                fn push_component(&mut self, component: $t) {
                    TypeRefMut::<ComponentContainer<$t>>::type_ref_mut(&mut self.1).push(self.0, component);
                }
            }
        )+
    };
}

#[macro_export]
macro_rules! add_entity {
    ( $i:ident; $($e:expr),+ $(,)?) => {
        $(
            $i.push_component($e);
        )+
        $i.0 += 1;
    };
}

#[macro_export]
macro_rules! system {
    ( $world:expr; $typ:ty ; $lambda:expr) => {
        let mut output = Vec::<(EntityID, $typ)>::new();
        TypeRef::<ComponentContainer<$typ>>::type_ref(&$world.1).iter().map($lambda).for_each(|(eid,data)|{
            output.push((eid, data));
        });
        let update = TypeRefMut::<ComponentContainer<$typ>>::type_ref_mut(&mut $world.1);
        for (eid, data) in output {
            if let Some(d) = update.get_mut(eid) {
                *d = data;
            }
        }
    };
    ( $world:expr; $typ1:ty; $typ2:ty ; $lambda:expr) => {
        let mut output = Vec::<(EntityID, $typ1)>::new();
        TypeRef::<ComponentContainer<$typ1>>::type_ref(&$world.1).iter()
        .zip_entity(TypeRef::<ComponentContainer<$typ2>>::type_ref(&$world.1))
        .map($lambda)
        .for_each(|(eid,data)|{
            output.push((eid, data));
        });
        let update = TypeRefMut::<ComponentContainer<$typ1>>::type_ref_mut(&mut $world.1);
        for (eid, data) in output {
            if let Some(d) = update.get_mut(eid) {
                *d = data;
            }
        }
    };
    ( $world:expr; $typ1:ty; $typ2:ty, $typ3:ty ; $lambda:expr) => {
        let mut output = Vec::<(EntityID, $typ1)>::new();
        TypeRef::<ComponentContainer<$typ1>>::type_ref(&$world.1).iter()
        .zip_entity2(TypeRef::<ComponentContainer<$typ2>>::type_ref(&$world.1), TypeRef::<ComponentContainer<$typ3>>::type_ref(&$world.1))
        .map($lambda)
        .for_each(|(eid,data)|{
            output.push((eid, data));
        });
        let update = TypeRefMut::<ComponentContainer<$typ1>>::type_ref_mut(&mut $world.1);
        for (eid, data) in output {
            if let Some(d) = update.get_mut(eid) {
                *d = data;
            }
        }
    };
}

#[cfg(test)]
mod tests {
    world! {
        World {
            i32,
            f32,
            u32,
        }
    }
    
    #[test]
    fn it_works() {
        let mut a = World::default();
        add_entity!(a; 1i32, 1f32);
        system!( a; i32; f32, u32; |(_,i,f,u)|{ (1,*i) });
    }
}