1pub 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 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}