1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
use crossbeam::channel::{Receiver, Sender}; use std::error::Error; pub struct Bus<T> where T: Copy, { subscriptions: Vec<(Box<dyn FnMut(T) -> bool + 'static>, Sender<T>)>, } impl<T> Bus<T> where T: Copy, { pub fn new() -> Self { Bus { subscriptions: vec![], } } pub fn send(&mut self, message: T) -> Result<(), crossbeam::channel::SendError<T>> { for v in self.subscriptions.iter_mut() { if v.0(message) { match v.1.send(message) { Ok(()) => (), Err(e) => { return Err(e); } } } } return Ok(()); } pub fn subscribe(&mut self, guard: impl FnMut(T) -> bool + 'static) -> Receiver<T> { let (sender, receiver) = crossbeam_channel::unbounded(); self.subscriptions.push((Box::new(guard), sender)); return receiver; } } #[cfg(test)] mod tests { use super::*; #[test] fn send_message() { let mut test_bus: Bus<&[u8]> = Bus::new(); assert_eq!(test_bus.send("test".as_bytes()), Ok(())); } #[test] fn send_message_and_receive() { let mut test_bus: Bus<&[u8]> = Bus::new(); let receiver = test_bus.subscribe(|x| return x == "test".as_bytes()); match test_bus.send("test".as_bytes()) { Ok(()) => { assert_eq!(receiver.recv().unwrap(), "test".as_bytes()); } Err(_) => return, } } }