argentum_event_business/lib.rs
1//! Event component
2//!
3//! The easiest way to work with events, listeners, and dispatchers
4//! Provides a macro to create and manage your own events
5
6///
7/// The way to create event and boilerplate to listening and dispatching
8///
9/// ```rust
10/// use argentum_event_business::event_boilerplate;
11///
12/// // Event type
13/// pub struct MyEvent {}
14///
15/// // Create a boilerplate
16/// event_boilerplate!(MyEvent, MyEventListenerTrait, MyEventDispatcher);
17///
18/// ```
19///
20/// It is equivalent of a code below.
21///
22/// ```rust
23/// use argentum_event_business::event_boilerplate;
24///
25/// pub struct MyEvent {}
26///
27/// pub trait MyEventListenerTrait {
28/// fn listen(&self, _e: &MyEvent) {}
29/// }
30///
31/// pub struct MyEventDispatcher<Listener: MyEventListenerTrait> {
32/// listeners: Vec<Listener>,
33/// }
34///
35/// impl<Listener: MyEventListenerTrait> MyEventDispatcher<Listener> {
36/// pub fn new(listeners: Vec<Listener>) -> MyEventDispatcher<Listener> {
37/// MyEventDispatcher { listeners }
38/// }
39///
40/// pub fn dispatch(&self, e: &MyEvent) {
41/// self.listeners.iter().for_each(move |l| {
42/// l.listen(e);
43/// });
44/// }
45/// }
46/// ```
47///
48/// Of course, you can do it manually but macro provides the shorter and easier way.
49///
50///
51/// Next step: create a listener
52///
53/// ```ignore
54/// pub struct MyListener {}
55///
56/// impl MyEventListenerTrait for MyListener {
57/// fn listen(&self, _e: &MyEvent) {
58/// println!("listened MyEvent")
59/// }
60/// }
61///```
62///
63/// Instantiate a listener, and a dispatcher. We mean that you will inject a dispatcher in your services
64///
65/// ```ignore
66/// let my_listener = MyListener {};
67/// let my_dispatcher = MyEventDispatcher::new(vec![my_listener]);
68/// ```
69///
70/// Now we can emit an event
71///
72/// ```ignore
73/// let e = MyEvent {};
74/// my_dispatcher.dispatch(&e);
75/// ```
76///
77#[macro_export]
78macro_rules! event_boilerplate {
79 ($event: ident, $listener_trait:ident, $dispatcher:ident) => {
80 pub trait $listener_trait {
81 fn listen(&self, _e: &$event) {}
82 }
83
84 pub struct $dispatcher<Listener: $listener_trait> {
85 listeners: Vec<Listener>,
86 }
87
88 impl<Listener: $listener_trait> $dispatcher<Listener> {
89 pub fn new(listeners: Vec<Listener>) -> $dispatcher<Listener> {
90 $dispatcher { listeners }
91 }
92
93 pub fn dispatch(&self, e: &$event) {
94 self.listeners.iter().for_each(move |l| {
95 l.listen(e);
96 });
97 }
98 }
99 };
100}
101
102#[cfg(test)]
103mod test {
104 pub struct TestEvent {
105 user_id: u8,
106 }
107
108 impl TestEvent {
109 pub fn new(user_id: u8) -> TestEvent {
110 TestEvent { user_id }
111 }
112 }
113
114 event_boilerplate!(TestEvent, TestListenerTrait, TestEventDispatcher);
115
116 pub struct TestListener {}
117
118 impl TestListenerTrait for TestListener {
119 fn listen(&self, e: &TestEvent) {
120 println!("listened TestEvent for user. user_id {}", e.user_id)
121 }
122 }
123
124 #[test]
125 fn test() -> Result<(), &'static str> {
126 let listener = TestListener {};
127 let dispatcher = TestEventDispatcher::new(vec![listener]);
128
129 let event = TestEvent::new(1);
130 dispatcher.dispatch(&event);
131
132 assert_eq!(1, 1);
133
134 Ok(())
135 }
136}