1
use paste::paste;
2
use uniplate::Uniplate;
3

            
4
macro_rules! event_handlers {
5
    (
6
        directions: [$($dir:ident),*]
7
    ) => {
8

            
9
        paste! {
10
        pub(crate) struct EventHandlers<T, M, R> {
11
            $(
12
                [<before_ $dir>]: Vec<fn(&T, &mut M)>,
13
                [<after_ $dir>]: Vec<fn(&T, &mut M)>,
14
            )*
15
            before_rule: Vec<fn(&T, &mut M, &R)>,
16
            after_rule: Vec<fn(&T, &mut M, &R, bool)>,
17
            after_apply: Vec<fn(&T, &mut M, &R)>,
18
            on_cache_hit: Vec<fn(&T, &mut M)>,
19
            on_cache_miss: Vec<fn(&T, &mut M)>,
20
        }
21

            
22
        #[allow(dead_code)]
23
        impl<T: Uniplate, M, R> EventHandlers<T, M, R> {
24
39255
            pub(crate) fn new() -> Self {
25
39255
                Self {
26
39255
                    $(
27
39255
                        [<before_ $dir>]: vec![],
28
39255
                        [<after_ $dir>]: vec![],
29
39255
                    )*
30
39255
                    before_rule: vec![],
31
39255
                    after_rule: vec![],
32
39255
                    after_apply: vec![],
33
39255
                    on_cache_hit: vec![],
34
39255
                    on_cache_miss: vec![],
35
39255
                }
36
39255
            }
37

            
38
            $(
39
2116389
                pub(crate) fn [<trigger_before_ $dir>](&self, node: &T, meta: &mut M) {
40
2116389
                    for f in &self.[<before_ $dir>] {
41
                        f(node, meta)
42
                    }
43
2116389
                }
44
2765953
                pub(crate) fn [<trigger_after_ $dir>](&self, node: &T, meta: &mut M) {
45
2765953
                    for f in &self.[<after_ $dir>] {
46
                        f(node, meta)
47
                    }
48
2765953
                }
49
                pub(crate) fn [<add_before_ $dir>](&mut self, handler: fn(&T, &mut M)) {
50
                    self.[<before_ $dir>].push(handler);
51
                }
52
                pub(crate) fn [<add_after_ $dir>](&mut self, handler: fn(&T, &mut M)) {
53
                    self.[<after_ $dir>].push(handler);
54
                }
55
            )*
56

            
57
403229918
            pub(crate) fn trigger_before_rule(&self, node: &T, meta: &mut M, rule: &R) {
58
403229918
                for f in &self.before_rule {
59
14
                    f(node, meta, rule)
60
                }
61
403229918
            }
62

            
63
403229918
            pub(crate) fn trigger_after_rule(&self, node: &T, meta: &mut M, rule: &R, applicable: bool) {
64
403229918
                for f in &self.after_rule {
65
14
                    f(node, meta, rule, applicable)
66
                }
67
403229918
            }
68

            
69
290895
            pub(crate) fn trigger_on_apply(&self, node: &T, meta: &mut M, rule: &R) {
70
290895
                for f in &self.after_apply {
71
3
                    f(node, meta, rule)
72
                }
73
290895
            }
74

            
75
1
            pub(crate) fn add_before_rule(&mut self, handler: fn(&T, &mut M, &R)) {
76
1
                self.before_rule.push(handler);
77
1
            }
78

            
79
1
            pub(crate) fn add_after_rule(&mut self, handler: fn(&T, &mut M, &R, bool)) {
80
1
                self.after_rule.push(handler);
81
1
            }
82

            
83
1
            pub(crate) fn add_after_apply(&mut self, handler: fn(&T, &mut M, &R)) {
84
1
                self.after_apply.push(handler);
85
1
            }
86

            
87
17
            pub(crate) fn trigger_on_cache_hit(&self, node: &T, meta: &mut M) {
88
17
                for f in &self.on_cache_hit {
89
7
                    f(node, meta)
90
                }
91
17
            }
92

            
93
95501317
            pub(crate) fn trigger_on_cache_miss(&self, node: &T, meta: &mut M) {
94
95501317
                for f in &self.on_cache_miss {
95
14
                    f(node, meta)
96
                }
97
95501317
            }
98

            
99
1
            pub(crate) fn add_on_cache_hit(&mut self, handler: fn(&T, &mut M)) {
100
1
                self.on_cache_hit.push(handler);
101
1
            }
102

            
103
1
            pub(crate) fn add_on_cache_miss(&mut self, handler: fn(&T, &mut M)) {
104
1
                self.on_cache_miss.push(handler);
105
1
            }
106
        }
107
    }};
108
}
109

            
110
// We don't need event handlers for "left" since we never move left
111
event_handlers! {
112
    directions: [up, down, right]
113
}