1
//! A builder type for constructing and configuring [`Engine`] instances.
2

            
3
use crate::engine::Engine;
4
use crate::events::EventHandlers;
5
use crate::helpers::{SelectorFn, select_first};
6
use crate::prelude::Rule;
7

            
8
use paste::paste;
9
use uniplate::Uniplate;
10

            
11
/// A builder type for constructing and configuring [`Engine`] instances.
12
pub struct EngineBuilder<T, M, R>
13
where
14
    T: Uniplate,
15
    R: Rule<T, M>,
16
{
17
    event_handlers: EventHandlers<T, M>,
18

            
19
    /// Groups of rules, each with a selector function.
20
    rule_groups: Vec<Vec<R>>,
21

            
22
    selector: SelectorFn<T, M, R>,
23
}
24

            
25
macro_rules! add_handler_fns {
26
    (
27
        directions: [$($dir:ident),*]
28
    ) => {
29
        paste! {$(
30
            /// Register an event handler to be called before moving $dir in the tree.
31
            pub fn [<add_before_ $dir>](mut self, handler: fn(&T, &mut M)) -> Self {
32
                self.event_handlers.[<add_before_ $dir>](handler);
33
                self
34
            }
35

            
36
            /// Register an event handler to be called after moving $dir one node in the tree.
37
            pub fn [<add_after_ $dir>](mut self, handler: fn(&T, &mut M)) -> Self {
38
                self.event_handlers.[<add_after_ $dir>](handler);
39
                self
40
            }
41
        )*}
42
    };
43
}
44

            
45
impl<T, M, R> EngineBuilder<T, M, R>
46
where
47
    T: Uniplate,
48
    R: Rule<T, M>,
49
{
50
    /// Creates a new builder instance with the default [`select_first`] selector.
51
    pub fn new() -> Self {
52
        EngineBuilder {
53
            event_handlers: EventHandlers::new(),
54
            rule_groups: Vec::new(),
55
            selector: select_first,
56
        }
57
    }
58

            
59
    /// Consumes the builder and returns the constructed [`Engine`] instance.
60
    pub fn build(self) -> Engine<T, M, R> {
61
        Engine {
62
            event_handlers: self.event_handlers,
63
            rule_groups: self.rule_groups,
64
            selector: self.selector,
65
        }
66
    }
67

            
68
    /// Adds a collection of rules with the same priority.
69
    ///
70
    /// These rules will have a lower priority than previously added groups.
71
    pub fn add_rule_group(mut self, rules: Vec<R>) -> Self {
72
        self.rule_groups.push(rules);
73
        self
74
    }
75

            
76
    /// Adds a single rule in a group by itself.
77
    ///
78
    /// This is a special case of [`add_rule_group`](EngineBuilder::add_rule_group).
79
    pub fn add_rule(self, rule: R) -> Self {
80
        self.add_rule_group(vec![rule])
81
    }
82

            
83
    /// Adds a collection of rule groups to the existing one.
84
    ///
85
    /// Rule groups maintain the same order and will be lower priority than existing groups.
86
    pub fn append_rule_groups(mut self, groups: Vec<Vec<R>>) -> Self {
87
        self.rule_groups.extend(groups);
88
        self
89
    }
90

            
91
    add_handler_fns! {
92
        directions: [up, down, right]
93
    }
94

            
95
    /// Sets the selector function to be used when multiple rules are applicable to the same node.
96
    ///
97
    /// See the [`morph`](Engine::morph) method of the Engine type for more information.
98
    pub fn set_selector(mut self, selector: SelectorFn<T, M, R>) -> Self {
99
        self.selector = selector;
100
        self
101
    }
102
}
103

            
104
impl<T, M, R> Default for EngineBuilder<T, M, R>
105
where
106
    T: Uniplate,
107
    R: Rule<T, M>,
108
{
109
    fn default() -> Self {
110
        Self::new()
111
    }
112
}
113

            
114
impl<T, M, R> From<EngineBuilder<T, M, R>> for Engine<T, M, R>
115
where
116
    T: Uniplate,
117
    R: Rule<T, M>,
118
{
119
    fn from(val: EngineBuilder<T, M, R>) -> Self {
120
        val.build()
121
    }
122
}