data_router/
lib.rs

1//! A library for creating event-based applications
2//!
3//! ## Overview
4//!
5//! The library consists of 2 traits:
6//! - [`Receive`][`receive::Receive`]: a generic interface for sending events
7//! - [`View`][`view::View`]: a generic interface for viewing events
8//!
9//! Viewer return;
10//! - [`DeleteView`][`view::DeleteView`]: flag to delete the viewer
11//!
12//! Receiver return, [`ReceiverResult`][`receive::ReceiverResult`]:
13//! - [`Continue`][`receive::ReceiverResult::Continue`]: continue processing the output as normal (like [`Some`])
14//! - [`Stop`][`receive::ReceiverResult::Stop`]: stop processing the output (like [`None`]`)
15//! - [`Delete`][`receive::ReceiverResult::Delete`]: gives back the event with the flag that the receiver should be
16//! deleted, this is specifically for communication with routers so that intercepts can be cleanly destructed while
17//! letting the event pass through
18//!
19//! The different ways to store receivers and viewers are:
20//! - [`RcLinker`][`rc_linker::RcLinker`] and [`ArcLinker`][`arc_linker::ArcLinker`]:
21//! a smart pointer that will mark any instances of [`RcLinked`][`rc_linker::rc_linked::RcLinked`] or
22//! [`ArcLinked`][`arc_linker::arc_linked::ArcLinked`] ready for deletion when dropped, cleaning up any
23//! dangling references.
24//! - [`Exposed`][`exposed::Exposed`]: a container for a receiver that allows multiple [`View`][`view::View`]ers to be
25//! prepended
26//! - [`Router`][`router::Router`]: a container for a receiver that allows another router to intercept the event at
27//! the beginning, by repeating the intercept function it will be delegated to lower routers, allowing a level of
28//! abstraction where an intercept does what is expected without breaking the rest of the router.
29//!
30//! ## Aproach
31//!
32//! The receivers function as a sort of lazy garbage collector.
33//!
34//! When receivers flags that they wish to be deleted ([`Delete`][`receive::ReceiverResult::Delete`]), it should
35//! be expected that everything occuring before the introduction of the flag was ran, including viewers and intercepters.
36//!
37//! **This mean if *[`Delete`][`receive::ReceiverResult::Delete`]* is received, it is expected that *all prior systems
38//! have ran* and responsibilty falls upon the receiver to *continue the event propgation with minimal interuptions*.**
39//!
40//! The exception to this is [`Stop`][`receive::ReceiverResult::Stop`], which marks that a decision has been made to exit
41//! the event propgation.
42//!
43//! **This means if *[`Stop`][`receive::ReceiverResult::Stop`]* is received, it is expected that *not all prior systems
44//! have ran* and responsibilty falls upon the receiver to *exit the event propgation with minimal impact*.**
45//!
46
47pub mod arc_linker;
48pub mod exposed;
49pub mod multi_exposed;
50pub mod multi_router;
51pub mod rc_linker;
52pub mod receive;
53pub mod router;
54pub mod view;
55
56pub use crate as event_horizon;
57pub use counted_map;
58
59#[cfg(test)]
60mod tests {
61    use std::{cell::RefCell, rc::Rc, thread};
62
63    use crate::{
64        multi_exposed::MultiExpose,
65        rc_linker::RcLinker,
66        receive::{Receive, ReceiverResult},
67        router::Router,
68        view::View,
69    };
70
71    #[test]
72    fn player_health() {
73        struct Player {
74            health: i32,
75        }
76        impl Receive<i32> for Player {
77            type Output = ();
78
79            fn send(&mut self, event: i32) -> ReceiverResult<i32, Self::Output> {
80                self.health += event;
81                ReceiverResult::Continue(())
82            }
83        }
84
85        struct Shielded {
86            shielded: bool,
87        }
88        impl Receive<i32> for Shielded {
89            type Output = i32;
90
91            fn send(&mut self, event: i32) -> ReceiverResult<i32, Self::Output> {
92                if self.shielded {
93                    ReceiverResult::Stop
94                } else {
95                    ReceiverResult::Continue(event)
96                }
97            }
98        }
99
100        let player = Rc::new(RefCell::new(Player { health: 100 }));
101        let shielded = Rc::new(RefCell::new(Shielded { shielded: false }));
102
103        let player_linker = RcLinker::new(player.clone());
104        let shielded_linker = RcLinker::new(shielded.clone());
105
106        let mut router = Router::new(player_linker.linked());
107
108        assert_eq!(player.borrow().health, 100);
109        assert!(!shielded.borrow().shielded);
110
111        router.send(-10);
112
113        assert_eq!(player.borrow().health, 90);
114        assert!(!shielded.borrow().shielded);
115
116        router.intercept_from_receiver(shielded_linker.linked());
117        router.send(-5);
118
119        assert_eq!(player.borrow().health, 85);
120        assert!(!shielded.borrow().shielded);
121
122        shielded.borrow_mut().shielded = true;
123        router.send(-20);
124
125        assert_eq!(player.borrow().health, 85);
126        assert!(shielded.borrow().shielded);
127
128        drop(shielded_linker);
129        router.send(-20);
130
131        assert_eq!(player.borrow().health, 65);
132    }
133
134    #[test]
135    fn multi_threaded() {
136        struct A(i32);
137        struct B(i32);
138
139        struct PassAndPrint;
140        impl Receive<A> for PassAndPrint {
141            type Output = thread::JoinHandle<i32>;
142
143            fn send(&mut self, event: A) -> ReceiverResult<A, Self::Output> {
144                ReceiverResult::Continue(thread::spawn(move || {
145                    thread::sleep(std::time::Duration::from_millis(1000));
146                    event.0
147                }))
148            }
149        }
150        impl Receive<B> for PassAndPrint {
151            type Output = thread::JoinHandle<i32>;
152
153            fn send(&mut self, event: B) -> ReceiverResult<B, Self::Output> {
154                ReceiverResult::Continue(thread::spawn(move || {
155                    thread::sleep(std::time::Duration::from_millis(1000));
156                    event.0
157                }))
158            }
159        }
160
161        let mut router_a = Router::new(PassAndPrint);
162        let mut router_b = Router::new(PassAndPrint);
163
164        let a = router_a.send(A(1)).unwrap_continue();
165        let b = router_b.send(B(2)).unwrap_continue();
166
167        assert_eq!(a.join().unwrap(), 1);
168        assert_eq!(b.join().unwrap(), 2);
169    }
170
171    #[test]
172    fn drop_test() {
173        struct Player {
174            name: String,
175        }
176        impl Receive<i32> for Player {
177            type Output = ();
178
179            fn send(&mut self, event: i32) -> ReceiverResult<i32, Self::Output> {
180                println!("Player: {} received event: {}", self.name, event);
181                ReceiverResult::Continue(())
182            }
183        }
184        impl View<i32> for Player {
185            fn view(&mut self, event: &i32) -> Option<crate::view::DeleteView> {
186                println!("Player: {} viewed event: {}", self.name, event);
187                None
188            }
189        }
190
191        let player_amy_linker = RcLinker::new(Player {
192            name: "Amy".to_string(),
193        });
194
195        let player_bob_linker = RcLinker::new(Player {
196            name: "Bob".to_string(),
197        });
198
199        let mut player_amy_router = Router::new_exposed(player_amy_linker.linked());
200
201        assert!(player_amy_router.send(10).is_continue());
202
203        player_amy_router
204            .get_receiver_mut()
205            .box_and_add_viewer(player_bob_linker.linked())
206            .unwrap();
207
208        assert!(player_amy_router.send(20).is_continue());
209
210        drop(player_bob_linker);
211
212        assert!(player_amy_router.send(30).is_continue());
213
214        drop(player_amy_linker);
215
216        let player_collin_linker = RcLinker::new(Player {
217            name: "Collin".to_string(),
218        });
219        player_amy_router
220            .get_receiver_mut()
221            .box_and_add_viewer(player_collin_linker.linked())
222            .unwrap();
223
224        assert!(player_amy_router.send(40).is_delete());
225
226        drop(player_collin_linker);
227    }
228
229    #[test]
230    fn nested_intercepts() {
231        struct Reader {
232            name: String,
233        }
234        impl Receive<i32> for Reader {
235            type Output = i32;
236
237            fn send(&mut self, event: i32) -> ReceiverResult<i32, Self::Output> {
238                println!("Reader: {} received event: {}", self.name, event);
239                ReceiverResult::Continue(event)
240            }
241        }
242
243        let reader_a = RcLinker::new(Reader {
244            name: "A".to_string(),
245        });
246        let reader_b = RcLinker::new(Reader {
247            name: "B".to_string(),
248        });
249        let reader_c = RcLinker::new(Reader {
250            name: "C".to_string(),
251        });
252
253        let mut router = Router::new(reader_a.linked());
254
255        assert!(router.send(10).is_continue());
256
257        router.intercept_from_receiver(reader_c.linked());
258
259        assert!(router.send(20).is_continue());
260
261        router.intercept_at_root_from_receiver(reader_b.linked());
262
263        assert!(router.send(30).is_continue());
264
265        drop(reader_b);
266
267        assert!(router.send(40).is_continue());
268
269        drop(reader_c);
270
271        assert!(router.send(50).is_continue());
272
273        drop(reader_a);
274
275        assert!(router.send(60).is_delete());
276    }
277
278    #[test]
279    fn multi_router() {
280        use crate::multi_router::MultiRoute;
281
282        mod isolated {
283            #![allow(unused)]
284
285            use crate::multi_router::{
286                impl_multi_router_intercept_trait, multi_router, multi_router_intercept_trait,
287            };
288
289            multi_router_intercept_trait!(pub LifeIntercept for i32 | bool);
290            multi_router_intercept_trait!(pub Empty for ());
291
292            multi_router!(
293                #[derive()]
294                pub PlayerMultiRouter {
295                    i as LifeIntercept where i32 => () | bool => (),
296                    e as Empty where () => ()
297                } else {
298                    String => String
299                }
300            );
301
302            multi_router!(pub ShieldedMultiRouter {
303                i as LifeIntercept where i32 | bool
304            });
305
306            // implements `LifeIntercept` for `ShieldedMultiRouter`
307            impl_multi_router_intercept_trait!(ShieldedMultiRouter as LifeIntercept for i32 | bool);
308        }
309
310        #[derive(Clone, Copy, Debug, PartialEq, Eq)]
311        pub enum Player {
312            Alive { health: i32 },
313            Dead,
314        }
315        impl Player {
316            pub fn alive(&self) -> Option<&i32> {
317                if let Self::Alive { health } = self {
318                    Some(health)
319                } else {
320                    None
321                }
322            }
323
324            pub fn dead(&self) -> Option<()> {
325                if let Self::Dead = self {
326                    Some(())
327                } else {
328                    None
329                }
330            }
331        }
332        impl Receive<i32> for Player {
333            type Output = ();
334
335            fn send(&mut self, event: i32) -> ReceiverResult<i32, Self::Output> {
336                if let Self::Alive { health } = self {
337                    *health += event;
338                };
339                ReceiverResult::Continue(())
340            }
341        }
342        impl Receive<bool> for Player {
343            type Output = ();
344
345            fn send(&mut self, event: bool) -> ReceiverResult<bool, Self::Output> {
346                if !event {
347                    *self = Self::Dead;
348                }
349                ReceiverResult::Continue(())
350            }
351        }
352        impl Receive<String> for Player {
353            type Output = String;
354
355            fn send(&mut self, event: String) -> ReceiverResult<String, Self::Output> {
356                ReceiverResult::Continue(format!("recieved event: {}", event))
357            }
358        }
359        impl Receive<()> for Player {
360            type Output = ();
361
362            fn send(&mut self, _: ()) -> ReceiverResult<(), Self::Output> {
363                ReceiverResult::Continue(())
364            }
365        }
366        impl std::fmt::Display for Player {
367            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
368                write!(
369                    f,
370                    "{}",
371                    match self {
372                        Player::Alive { health } => format!("Health: {}", health),
373                        Player::Dead => "Dead".to_string(),
374                    }
375                )
376            }
377        }
378
379        #[derive(Default, Clone, Copy, Debug, PartialEq, Eq)]
380        pub struct Shielded {
381            shielded: bool,
382        }
383        impl Receive<i32> for Shielded {
384            type Output = i32;
385
386            fn send(&mut self, event: i32) -> ReceiverResult<i32, Self::Output> {
387                if self.shielded {
388                    ReceiverResult::Stop
389                } else {
390                    ReceiverResult::Continue(event)
391                }
392            }
393        }
394        impl Receive<bool> for Shielded {
395            type Output = bool;
396
397            fn send(&mut self, event: bool) -> ReceiverResult<bool, Self::Output> {
398                if self.shielded {
399                    ReceiverResult::Stop
400                } else {
401                    ReceiverResult::Continue(event)
402                }
403            }
404        }
405
406        let mut multi_router = isolated::PlayerMultiRouter::new(Player::Alive { health: 100 });
407
408        assert!(multi_router.send(-10).is_continue());
409        assert_eq!(*multi_router.get_receiver().alive().unwrap(), 90);
410
411        let shielded_linker = RcLinker::new(Shielded { shielded: false });
412        multi_router.intercept(Box::new(isolated::ShieldedMultiRouter::new(
413            shielded_linker.linked(),
414        )) as Box<dyn isolated::LifeIntercept>);
415
416        assert!(multi_router.send(-10).is_continue());
417        assert_eq!(*multi_router.get_receiver().alive().unwrap(), 80);
418
419        shielded_linker.borrow_mut().as_mut().unwrap().shielded = true;
420
421        assert!(multi_router.send(false).is_stop());
422        assert_eq!(*multi_router.get_receiver().alive().unwrap(), 80);
423
424        let _: Box<dyn isolated::LifeIntercept> = multi_router.take_intercept().unwrap();
425
426        assert!(multi_router.send(false).is_continue());
427        assert_eq!(multi_router.get_receiver().dead(), Some(()));
428
429        assert_eq!(
430            multi_router
431                .send("no intercept".to_string())
432                .unwrap_continue(),
433            "recieved event: no intercept"
434        );
435
436        multi_router = isolated::PlayerMultiRouter::new(Player::Alive { health: 100 });
437
438        multi_router.intercept(Box::new(isolated::ShieldedMultiRouter::new(
439            shielded_linker.linked(),
440        )) as Box<dyn isolated::LifeIntercept>);
441
442        multi_router.intercept(Box::new(isolated::ShieldedMultiRouter::new(
443            shielded_linker.linked(),
444        )) as Box<dyn isolated::LifeIntercept>);
445
446        assert!(multi_router.send(false).is_stop());
447        assert_eq!(*multi_router.get_receiver().alive().unwrap(), 100);
448
449        println!("{}", multi_router);
450        println!("{:?}", multi_router);
451
452        (&mut multi_router as &mut dyn MultiRoute<dyn isolated::LifeIntercept>)
453            .delete_top_intercept();
454
455        assert!(multi_router.send(false).is_stop());
456        assert_eq!(*multi_router.get_receiver().alive().unwrap(), 100);
457
458        multi_router.intercept(Box::new(isolated::ShieldedMultiRouter::new(
459            shielded_linker.linked(),
460        )) as Box<dyn isolated::LifeIntercept>);
461
462        drop(shielded_linker);
463
464        assert!(multi_router.send(false).is_continue());
465        assert_eq!(multi_router.get_receiver().dead(), Some(()));
466    }
467
468    #[test]
469    fn multi_exposed() {
470        mod isolated {
471            crate::multi_exposed::multi_exposed_trait!(pub View1 for i32 | bool);
472            crate::multi_exposed::multi_exposed_trait!(pub View2 for ());
473
474            crate::multi_exposed::multi_exposed!(
475                #[derive()]
476                pub MultiExposed {
477                    view1 as View1 for i32 => () | bool => (),
478                    view2 as View2 for () => ()
479                } else {
480                    String => String
481                }
482            );
483        }
484
485        #[derive(Clone, Copy, Debug, PartialEq, Eq)]
486        pub enum Player {
487            Alive { health: i32 },
488            Dead,
489        }
490        impl Player {
491            pub fn alive(&self) -> Option<&i32> {
492                if let Self::Alive { health } = self {
493                    Some(health)
494                } else {
495                    None
496                }
497            }
498
499            pub fn dead(&self) -> Option<()> {
500                if let Self::Dead = self {
501                    Some(())
502                } else {
503                    None
504                }
505            }
506        }
507        impl Receive<i32> for Player {
508            type Output = ();
509
510            fn send(&mut self, event: i32) -> ReceiverResult<i32, Self::Output> {
511                if let Self::Alive { health } = self {
512                    *health += event;
513                };
514                ReceiverResult::Continue(())
515            }
516        }
517        impl Receive<bool> for Player {
518            type Output = ();
519
520            fn send(&mut self, event: bool) -> ReceiverResult<bool, Self::Output> {
521                if !event {
522                    *self = Self::Dead;
523                }
524                ReceiverResult::Continue(())
525            }
526        }
527        impl Receive<String> for Player {
528            type Output = String;
529
530            fn send(&mut self, event: String) -> ReceiverResult<String, Self::Output> {
531                ReceiverResult::Continue(format!("recieved event: {}", event))
532            }
533        }
534        impl Receive<()> for Player {
535            type Output = ();
536
537            fn send(&mut self, _: ()) -> ReceiverResult<(), Self::Output> {
538                ReceiverResult::Continue(())
539            }
540        }
541        impl std::fmt::Display for Player {
542            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
543                write!(
544                    f,
545                    "{}",
546                    match self {
547                        Player::Alive { health } => format!("Health: {}", health),
548                        Player::Dead => "Dead".to_string(),
549                    }
550                )
551            }
552        }
553
554        #[derive(Default, Clone, Debug, PartialEq, Eq)]
555        pub struct Viewer1 {
556            pub string_vec: Vec<String>,
557        }
558        impl View<i32> for Viewer1 {
559            fn view(&mut self, event: &i32) -> Option<crate::view::DeleteView> {
560                self.string_vec.push(format!("saw i32: {}", event));
561                None
562            }
563        }
564        impl View<bool> for Viewer1 {
565            fn view(&mut self, event: &bool) -> Option<crate::view::DeleteView> {
566                self.string_vec.push(format!("saw bool: {}", event));
567                None
568            }
569        }
570
571        #[derive(Default, Clone, Copy, Debug, PartialEq, Eq)]
572        pub struct Viewer2 {
573            pub count: u8,
574        }
575        impl View<()> for Viewer2 {
576            fn view(&mut self, _: &()) -> Option<crate::view::DeleteView> {
577                self.count += 1;
578                None
579            }
580        }
581
582        let mut multi_router = isolated::MultiExposed::new(Player::Alive { health: 100 });
583
584        assert!(multi_router.send(-10).is_continue());
585        assert_eq!(*multi_router.get_receiver().alive().unwrap(), 90);
586
587        let viewer1_linker = RcLinker::new(Viewer1::default());
588        let _ = multi_router
589            .add_viewer(Box::new(viewer1_linker.linked()) as Box<dyn isolated::View1>)
590            .unwrap();
591
592        assert!(multi_router.send(-10).is_continue());
593        assert_eq!(*multi_router.get_receiver().alive().unwrap(), 80);
594
595        println!("{:?}", viewer1_linker);
596        drop(viewer1_linker);
597
598        let viewer2_linker = RcLinker::new(Viewer2 { count: 0 });
599        let _ = multi_router
600            .add_viewer(Box::new(viewer2_linker.linked()) as Box<dyn isolated::View2>)
601            .unwrap();
602
603        assert!(multi_router.send(false).is_continue());
604        assert_eq!(multi_router.get_receiver().dead(), Some(()));
605
606        assert_eq!(
607            multi_router
608                .send("no intercept".to_string())
609                .unwrap_continue(),
610            "recieved event: no intercept"
611        );
612    }
613}