summaryrefslogtreecommitdiff
path: root/ecs/src/event.rs
blob: 1a4edccf883236a765ead3b698881d74355ebdd3 (plain)
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
use std::any::TypeId;
use std::fmt::Debug;
use std::hash::{DefaultHasher, Hash, Hasher};

use seq_macro::seq;

pub mod component;

pub trait Event: Debug + 'static
{
    /// Returns the ID of this event.
    #[must_use]
    fn id() -> Id
    where
        Self: Sized,
    {
        Id::new::<Self, ()>(None)
    }
}

pub mod start;

/// The ID of a [`Event`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Id
{
    inner: TypeId,
    extra: Option<u64>,
}

impl Id
{
    #[must_use]
    pub fn new<EventT, Extra>(extra: Option<Extra>) -> Self
    where
        EventT: Event,
        Extra: Hash,
    {
        Self {
            inner: TypeId::of::<EventT>(),
            extra: extra.map(|extra| {
                let mut hasher = DefaultHasher::new();

                extra.hash(&mut hasher);

                hasher.finish()
            }),
        }
    }
}

pub trait Ids
{
    type Iter<'a>: Iterator<Item = &'a Id>
    where
        Self: 'a;

    fn iter(&self) -> Self::Iter<'_>;
}

/// A sequence of events.
pub trait Sequence
{
    type Ids: Ids;

    fn ids() -> Self::Ids;
}

macro_rules! impl_sequence {
    ($c: tt) => {
        seq!(I in 0..=$c {
            impl Ids for [Id; $c + 1]
            {
                type Iter<'a> = std::slice::Iter<'a, Id>;

                fn iter(&self) -> Self::Iter<'_> {
                    self.into_iter()
                }
            }

            impl<#(Event~I: Event,)*> Sequence for (#(Event~I,)*) {
                type Ids = [Id; $c + 1];

                fn ids() -> Self::Ids {
                    [#(
                        Event~I::id(),
                    )*]
                }
            }
        });
    };
}

seq!(C in 0..=64 {
    impl_sequence!(C);
});